Changeset 347768d in mainline for uspace/srv/inet/pdu.c
- Timestamp:
- 2012-04-11T05:52:47Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7f95c904
- Parents:
- 7094e196
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/inet/pdu.c
r7094e196 r347768d 41 41 #include <fibril_synch.h> 42 42 #include <io/log.h> 43 #include <macros.h> 43 44 #include <mem.h> 44 45 #include <stdlib.h> … … 88 89 89 90 /** Encode Internet PDU. 90 */ 91 int inet_pdu_encode(inet_packet_t *packet, void **rdata, size_t *rsize) 91 * 92 * Encode internet packet into PDU (serialized form). Will encode a 93 * fragment of the payload starting at offset @a offs. The resulting 94 * PDU will have at most @a mtu bytes. @a *roffs will be set to the offset 95 * of remaining payload. If some data is remaining, the MF flag will 96 * be set in the header, otherwise the offset will equal @a packet->size. 97 * 98 * @param packet Packet to encode 99 * @param offs Offset into packet payload (in bytes) 100 * @param mtu MTU (Maximum Transmission Unit) in bytes 101 * @param rdata Place to store pointer to allocated data buffer 102 * @param rsize Place to store size of allocated data buffer 103 * @param roffs Place to store offset of remaning data 104 */ 105 int inet_pdu_encode(inet_packet_t *packet, size_t offs, size_t mtu, 106 void **rdata, size_t *rsize, size_t *roffs) 92 107 { 93 108 void *data; … … 98 113 uint16_t chksum; 99 114 uint16_t ident; 100 115 uint16_t flags_foff; 116 uint16_t foff; 117 size_t fragoff_limit; 118 size_t xfer_size; 119 size_t spc_avail; 120 size_t rem_offs; 121 122 /* Upper bound for fragment offset field */ 123 fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l); 124 125 /* Verify that total size of datagram is within reasonable bounds */ 126 if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit) 127 return ELIMIT; 128 129 hdr_size = sizeof(ip_header_t); 130 data_offs = ROUND_UP(hdr_size, 4); 131 132 assert(offs % FRAG_OFFS_UNIT == 0); 133 assert(offs / FRAG_OFFS_UNIT < fragoff_limit); 134 135 /* Value for the fragment offset field */ 136 foff = offs / FRAG_OFFS_UNIT; 137 138 if (hdr_size >= mtu) 139 return EINVAL; 140 141 /* Amount of space in the PDU available for payload */ 142 spc_avail = mtu - hdr_size; 143 144 /* Amount of data (payload) to transfer */ 145 xfer_size = min(packet->size - offs, spc_avail); 146 xfer_size -= (xfer_size % FRAG_OFFS_UNIT); 147 148 /* Total PDU size */ 149 size = hdr_size + xfer_size; 150 151 /* Offset of remaining payload */ 152 rem_offs = offs + xfer_size; 153 154 /* Flags */ 155 flags_foff = 156 (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) + 157 (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) + 158 (foff << FF_FRAGOFF_l); 159 160 data = calloc(size, 1); 161 if (data == NULL) 162 return ENOMEM; 163 164 /* Allocate identifier */ 101 165 fibril_mutex_lock(&ip_ident_lock); 102 166 ident = ++ip_ident; 103 167 fibril_mutex_unlock(&ip_ident_lock); 104 168 105 hdr_size = sizeof(ip_header_t); 106 size = hdr_size + packet->size; 107 data_offs = ROUND_UP(hdr_size, 4); 108 109 data = calloc(size, 1); 110 if (data == NULL) 111 return ENOMEM; 112 169 /* Encode header fields */ 113 170 hdr = (ip_header_t *)data; 114 171 hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t)); … … 116 173 hdr->tot_len = host2uint16_t_be(size); 117 174 hdr->id = host2uint16_t_be(ident); 118 hdr->flags_foff = host2uint16_t_be(packet->df ? 119 BIT_V(uint16_t, FF_FLAG_DF) : 0); 175 hdr->flags_foff = host2uint16_t_be(flags_foff); 120 176 hdr->ttl = packet->ttl; 121 177 hdr->proto = packet->proto; … … 124 180 hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4); 125 181 182 /* Compute checksum */ 126 183 chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size); 127 184 hdr->chksum = host2uint16_t_be(chksum); 128 185 129 memcpy((uint8_t *)data + data_offs, packet->data, packet->size); 186 /* Copy payload */ 187 memcpy((uint8_t *)data + data_offs, packet->data + offs, xfer_size); 130 188 131 189 *rdata = data; 132 190 *rsize = size; 191 *roffs = rem_offs; 192 133 193 return EOK; 134 194 }
Note:
See TracChangeset
for help on using the changeset viewer.