* Construct and reliably send a debugnet packet. May fail from a resource * shortage or extreme number of unacknowledged retransmissions. Wait for * an acknowledgement before returning. Splits packets into chunks small * enough to be sent without fragmentation (looks up the interface MTU) * * Parameters: * type debugnet packet type (HERALD, FINISHED, ...) * data data * datalen data size
| 233 | * int see errno.h, 0 for success |
| 234 | */ |
| 235 | int |
| 236 | debugnet_send(struct debugnet_pcb *pcb, uint32_t type, const void *data, |
| 237 | uint32_t datalen, const struct debugnet_proto_aux *auxdata) |
| 238 | { |
| 239 | struct debugnet_msg_hdr *dn_msg_hdr; |
| 240 | struct mbuf *m, *m2; |
| 241 | uint64_t want_acks; |
| 242 | uint32_t i, pktlen, sent_so_far; |
| 243 | int retries, polls, error; |
| 244 | |
| 245 | if (pcb->dp_state == DN_STATE_REMOTE_CLOSED) |
| 246 | return (ECONNRESET); |
| 247 | |
| 248 | want_acks = 0; |
| 249 | pcb->dp_rcvd_acks = 0; |
| 250 | retries = 0; |
| 251 | |
| 252 | retransmit: |
| 253 | /* Chunks can be too big to fit in packets. */ |
| 254 | for (i = sent_so_far = 0; sent_so_far < datalen || |
| 255 | (i == 0 && datalen == 0); i++) { |
| 256 | pktlen = datalen - sent_so_far; |
| 257 | |
| 258 | /* Bound: the interface MTU (assume no IP options). */ |
| 259 | pktlen = min(pktlen, pcb->dp_ifp->if_mtu - |
| 260 | sizeof(struct udpiphdr) - sizeof(struct debugnet_msg_hdr)); |
| 261 | |
| 262 | /* |
| 263 | * Check if it is retransmitting and this has been ACKed |
| 264 | * already. |
| 265 | */ |
| 266 | if ((pcb->dp_rcvd_acks & (1 << i)) != 0) { |
| 267 | sent_so_far += pktlen; |
| 268 | continue; |
| 269 | } |
| 270 | |
| 271 | /* |
| 272 | * Get and fill a header mbuf, then chain data as an extended |
| 273 | * mbuf. |
| 274 | */ |
| 275 | m = m_gethdr(M_NOWAIT, MT_DATA); |
| 276 | if (m == NULL) { |
| 277 | printf("%s: Out of mbufs\n", __func__); |
| 278 | return (ENOBUFS); |
| 279 | } |
| 280 | m->m_len = sizeof(struct debugnet_msg_hdr); |
| 281 | m->m_pkthdr.len = sizeof(struct debugnet_msg_hdr); |
| 282 | MH_ALIGN(m, sizeof(struct debugnet_msg_hdr)); |
| 283 | dn_msg_hdr = mtod(m, struct debugnet_msg_hdr *); |
| 284 | dn_msg_hdr->mh_seqno = htonl(pcb->dp_seqno + i); |
| 285 | dn_msg_hdr->mh_type = htonl(type); |
| 286 | dn_msg_hdr->mh_len = htonl(pktlen); |
| 287 | |
| 288 | if (auxdata != NULL) { |
| 289 | dn_msg_hdr->mh_offset = |
| 290 | htobe64(auxdata->dp_offset_start + sent_so_far); |
| 291 | dn_msg_hdr->mh_aux2 = htobe32(auxdata->dp_aux2); |
| 292 | } else { |
no test coverage detected