Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 347768d in mainline


Ignore:
Timestamp:
2012-04-11T05:52:47Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
7f95c904
Parents:
7094e196
Message:

Fragmentation of outgoing datagrams, default link MTU.

Location:
uspace
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/inetcfg/inetcfg.c

    r7094e196 r347768d  
    373373                }
    374374
    375                 printf("    %s %s %s\n", astr, linfo.name,
    376                     ainfo.name);
     375                printf("    %s %s %s %zu\n", astr, linfo.name,
     376                    ainfo.name, linfo.def_mtu);
    377377
    378378                free(ainfo.name);
  • uspace/lib/c/generic/inetcfg.c

    r7094e196 r347768d  
    276276
    277277        linfo->name = str_dup(name_buf);
     278        linfo->def_mtu = IPC_GET_ARG1(answer);
    278279
    279280        return EOK;
  • uspace/lib/c/include/inet/inetcfg.h

    r7094e196 r347768d  
    6161        /** Link service name */
    6262        char *name;
     63        /** Default MTU */
     64        size_t def_mtu;
    6365} inet_link_info_t;
    6466
  • uspace/srv/inet/inet.h

    r7094e196 r347768d  
    8888        /** Link service name */
    8989        char *name;
     90        /** Default MTU */
     91        size_t def_mtu;
    9092} inet_link_info_t;
    9193
     
    125127        async_sess_t *sess;
    126128        iplink_t *iplink;
     129        size_t def_mtu;
    127130} inet_link_t;
    128131
  • uspace/srv/inet/inet_link.c

    r7094e196 r347768d  
    161161
    162162        ilink->svc_id = sid;
     163        ilink->iplink = NULL;
    163164
    164165        rc = loc_service_get_name(sid, &ilink->svc_name);
     
    177178        if (rc != EOK) {
    178179                log_msg(LVL_ERROR, "Failed opening IP link '%s'",
     180                    ilink->svc_name);
     181                goto error;
     182        }
     183
     184        rc = iplink_get_mtu(ilink->iplink, &ilink->def_mtu);
     185        if (rc != EOK) {
     186                log_msg(LVL_ERROR, "Failed determinning MTU of link '%s'",
    179187                    ilink->svc_name);
    180188                goto error;
     
    211219
    212220error:
     221        if (ilink->iplink != NULL)
     222                iplink_close(ilink->iplink);
    213223        inet_link_delete(ilink);
    214224        return rc;
     
    241251        inet_packet_t packet;
    242252        int rc;
    243 
    244         /* XXX Fragment packet */
     253        size_t offs, roffs;
     254
     255        /*
     256         * Fill packet structure. Fragmentation is performed by
     257         * inet_pdu_encode().
     258         */
    245259        packet.src = dgram->src;
    246260        packet.dest = dgram->dest;
     
    254268        sdu.lsrc.ipv4 = lsrc->ipv4;
    255269        sdu.ldest.ipv4 = ldest->ipv4;
    256         rc = inet_pdu_encode(&packet, &sdu.data, &sdu.size);
    257         if (rc != EOK)
    258                 return rc;
    259 
    260         rc = iplink_send(ilink->iplink, &sdu);
    261         free(sdu.data);
     270
     271        offs = 0;
     272        do {
     273                /* Encode one fragment */
     274                rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
     275                    &sdu.size, &roffs);
     276                if (rc != EOK)
     277                        return rc;
     278
     279                /* Send the PDU */
     280                rc = iplink_send(ilink->iplink, &sdu);
     281                free(sdu.data);
     282
     283                offs = roffs;
     284        } while (offs < packet.size);
    262285
    263286        return rc;
  • uspace/srv/inet/inet_std.h

    r7094e196 r347768d  
    9090};
    9191
     92/** Fragment offset is expressed in units of 8 bytes */
     93#define FRAG_OFFS_UNIT 8
     94
    9295#endif
    9396
  • uspace/srv/inet/inetcfg.c

    r7094e196 r347768d  
    164164
    165165        linfo->name = str_dup(ilink->svc_name);
     166        linfo->def_mtu = ilink->def_mtu;
    166167        return EOK;
    167168}
     
    464465        free(linfo.name);
    465466
    466         async_answer_0(callid, retval);
     467        async_answer_1(callid, retval, linfo.def_mtu);
    467468}
    468469
  • uspace/srv/inet/pdu.c

    r7094e196 r347768d  
    4141#include <fibril_synch.h>
    4242#include <io/log.h>
     43#include <macros.h>
    4344#include <mem.h>
    4445#include <stdlib.h>
     
    8889
    8990/** 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 */
     105int inet_pdu_encode(inet_packet_t *packet, size_t offs, size_t mtu,
     106    void **rdata, size_t *rsize, size_t *roffs)
    92107{
    93108        void *data;
     
    98113        uint16_t chksum;
    99114        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 */
    101165        fibril_mutex_lock(&ip_ident_lock);
    102166        ident = ++ip_ident;
    103167        fibril_mutex_unlock(&ip_ident_lock);
    104168
    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 */
    113170        hdr = (ip_header_t *)data;
    114171        hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
     
    116173        hdr->tot_len = host2uint16_t_be(size);
    117174        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);
    120176        hdr->ttl = packet->ttl;
    121177        hdr->proto = packet->proto;
     
    124180        hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4);
    125181
     182        /* Compute checksum */
    126183        chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size);
    127184        hdr->chksum = host2uint16_t_be(chksum);
    128185
    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);
    130188
    131189        *rdata = data;
    132190        *rsize = size;
     191        *roffs = rem_offs;
     192
    133193        return EOK;
    134194}
  • uspace/srv/inet/pdu.h

    r7094e196 r347768d  
    4545extern uint16_t inet_checksum_calc(uint16_t, void *, size_t);
    4646
    47 extern int inet_pdu_encode(inet_packet_t *, void **, size_t *);
     47extern int inet_pdu_encode(inet_packet_t *, size_t, size_t, void **,
     48    size_t *, size_t *);
    4849extern int inet_pdu_decode(void *, size_t, inet_packet_t *);
    4950
Note: See TracChangeset for help on using the changeset viewer.