diff options
author | Jakub Grajciar <jgrajcia@cisco.com> | 2018-03-29 13:15:10 +0200 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2018-03-30 20:48:36 +0000 |
commit | 3744fc7abce0cf8694d64b670589e35c6d7bf881 (patch) | |
tree | 04f5f42458a1ab4f3f4109f890e998221b22e622 /extras/libmemif/examples/icmp_responder | |
parent | 17ddc0fee1bc20d0da84dd70bb579c8844a48ef4 (diff) |
libmemif: zero-copy-slave mode + header space
Slave is now able to dequeue buffers from rx queue and enqueue them to tx queue
(zero-copy operation). Slave can produce buffers with headroom, which will allow adding
encap without copy.
Change-Id: Ia189f8de1a68be787545ed46cf78d36403e7e9bf
Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
Diffstat (limited to 'extras/libmemif/examples/icmp_responder')
-rw-r--r-- | extras/libmemif/examples/icmp_responder/icmp_proto.c | 186 | ||||
-rw-r--r-- | extras/libmemif/examples/icmp_responder/icmp_proto.h | 16 | ||||
-rw-r--r-- | extras/libmemif/examples/icmp_responder/main.c | 15 |
3 files changed, 210 insertions, 7 deletions
diff --git a/extras/libmemif/examples/icmp_responder/icmp_proto.c b/extras/libmemif/examples/icmp_responder/icmp_proto.c index b27abb6a231..e1d255aca27 100644 --- a/extras/libmemif/examples/icmp_responder/icmp_proto.c +++ b/extras/libmemif/examples/icmp_responder/icmp_proto.c @@ -37,6 +37,7 @@ #include <net/if_arp.h> #include <asm/byteorder.h> #include <byteswap.h> +#include <assert.h> #include <icmp_proto.h> @@ -337,3 +338,188 @@ generate_packet (void *pck, uint32_t * size, uint8_t saddr[4], return 0; } + +int +generate_packet2 (void *pck, uint32_t * size, uint8_t saddr[4], + uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq, + icmpr_flow_mode_t mode) +{ + struct ether_header *eh; + struct iphdr *ip; + struct icmphdr *icmp; + + *size = 0; + + if (mode == ICMPR_FLOW_MODE_ETH) + { + eh = (struct ether_header *) pck; + *size += generate_eth (eh, hw_daddr); + } + + ip = (struct iphdr *) (pck + *size); + *size += generate_ip (ip, saddr, daddr); + + icmp = (struct icmphdr *) (pck + *size); + *size += generate_icmp (icmp, seq); + + ((struct icmphdr *) (pck + *size - sizeof (struct icmphdr)))->checksum = + cksum (pck + *size - sizeof (struct icmphdr), sizeof (struct icmphdr)); + + ip->tot_len = __bswap_16 (*size - sizeof (struct ether_header)); + ip->check = 0; + ip->check = cksum (ip, sizeof (struct iphdr)); + + return 0; +} + +#define GET_HEADER(out,hdr,src,off) do { \ + out = (hdr*)(src + off); \ + off += sizeof (hdr); \ + } while (0) + +int +resolve_packet2 (void *pck, uint32_t * size, uint8_t ip_addr[4]) +{ + struct ether_header *eh; + struct ether_arp *eah; + struct iphdr *ip; + struct icmphdr *icmp; + uint32_t offset = 0; + + if (pck == NULL) + return 0; + + GET_HEADER (eh, struct ether_header, pck, offset); + + memcpy (eh->ether_dhost, eh->ether_shost, 6); + memcpy (eh->ether_shost, "aaaaaa", 6); + + if (eh->ether_type == 0x0608) + { + GET_HEADER (eah, struct ether_arp, pck, offset); + struct arphdr *arp = &eah->ea_hdr; + + arp->ar_hrd = __bswap_16 (ARPHRD_ETHER); + arp->ar_pro = __bswap_16 (0x0800); + + arp->ar_hln = 6; + arp->ar_pln = 4; + + arp->ar_op = __bswap_16 (ARPOP_REPLY); + + memcpy (eah->arp_tha, eah->arp_sha, 6); + memcpy (eah->arp_tpa, eah->arp_spa, 4); + + memcpy (eah->arp_sha, eh->ether_shost, 6); + memcpy (eah->arp_spa, ip_addr, 4); + } + + else if (eh->ether_type == 0x0008) + { + GET_HEADER (ip, struct iphdr, pck, offset); + + if (ip->protocol == 1) + { + ip->ihl = 5; + ip->version = 4; + ip->tos = 0; + ip->tot_len = 0x0000; + ip->id = 0; + ip->frag_off = 0; + ip->ttl = 0x40; + ip->protocol = 1; + ip->check = 0x0000; + ip->daddr = ip->saddr; + ((uint8_t *) & ip->saddr)[0] = ip_addr[0]; + ((uint8_t *) & ip->saddr)[1] = ip_addr[1]; + ((uint8_t *) & ip->saddr)[2] = ip_addr[2]; + ((uint8_t *) & ip->saddr)[3] = ip_addr[3]; + + GET_HEADER (icmp, struct icmphdr, pck, offset); + + icmp->type = 0x00; + icmp->code = 0; + icmp->checksum = cksum (icmp, sizeof (struct icmphdr)); + + /* rest is payload */ + offset = *size; + + ip->tot_len = __bswap_16 (offset - sizeof (struct ether_header)); + ip->check = cksum (ip, sizeof (struct iphdr)); + } + } + + assert (offset == *size && "unsupported protocol"); + return 0; +} + + +int +resolve_packet3 (void **pck_, uint32_t * size, uint8_t ip_addr[4]) +{ + struct ether_header *eh; + struct ether_arp *eah; + struct iphdr *ip; + struct icmphdr *icmp; + int32_t offset = 0; + uint16_t encap_size = sizeof (struct ether_header); + void *pck = *pck_; + + if (pck == NULL) + return 0; + + *pck_ -= encap_size; + offset -= encap_size; + + GET_HEADER (eh, struct ether_header, pck, offset); + + uint8_t hw_daddr[6]; + memset (hw_daddr, 0, sizeof (uint8_t) * 6); + + generate_eth (eh, hw_daddr); + + if (eh->ether_type == 0x0008) + { + GET_HEADER (ip, struct iphdr, pck, offset); + + if (ip->protocol == 1) + { + ip->ihl = 5; + ip->version = 4; + ip->tos = 0; + ip->tot_len = 0x0000; + ip->id = 0; + ip->frag_off = 0; + ip->ttl = 0x40; + ip->protocol = 1; + ip->check = 0x0000; + ip->daddr = ip->saddr; + ((uint8_t *) & ip->saddr)[0] = ip_addr[0]; + ((uint8_t *) & ip->saddr)[1] = ip_addr[1]; + ((uint8_t *) & ip->saddr)[2] = ip_addr[2]; + ((uint8_t *) & ip->saddr)[3] = ip_addr[3]; + + GET_HEADER (icmp, struct icmphdr, pck, offset); + + icmp->type = 0x00; + icmp->code = 0; + icmp->checksum = cksum (icmp, sizeof (struct icmphdr)); + + /* rest is payload */ + offset = *size; + + ip->tot_len = __bswap_16 (offset - sizeof (struct ether_header)); + ip->check = cksum (ip, sizeof (struct iphdr)); + } + } + + offset += encap_size; + + assert (offset != *size && + "new packet length must be increased by encap size"); + + /* overwrite packet size */ + *size = offset; + + return 0; +} diff --git a/extras/libmemif/examples/icmp_responder/icmp_proto.h b/extras/libmemif/examples/icmp_responder/icmp_proto.h index ca72b2fe026..1575719bd6a 100644 --- a/extras/libmemif/examples/icmp_responder/icmp_proto.h +++ b/extras/libmemif/examples/icmp_responder/icmp_proto.h @@ -18,12 +18,28 @@ #ifndef _ICMP_PROTO_H_ #define _ICMP_PROTO_H_ +typedef enum +{ + ICMPR_FLOW_MODE_ETH = 0, + ICMPR_FLOW_MODE_IP, +} icmpr_flow_mode_t; + int resolve_packet (void *in_pck, ssize_t in_size, void *out_pck, uint32_t * out_size, uint8_t ip_addr[4]); +/* resolve packet in place */ +int resolve_packet2 (void *pck, uint32_t * size, uint8_t ip_addr[4]); + +/* resolve packet in place and add eth encap */ +int resolve_packet3 (void **pck, uint32_t * size, uint8_t ip_addr[4]); + int generate_packet (void *pck, uint32_t * size, uint8_t saddr[4], uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq); +int generate_packet2 (void *pck, uint32_t * size, uint8_t saddr[4], + uint8_t daddr[4], uint8_t hw_daddr[6], uint32_t seq, + icmpr_flow_mode_t); + int print_packet (void *pck); #endif /* _ICMP_PROTO_H_ */ diff --git a/extras/libmemif/examples/icmp_responder/main.c b/extras/libmemif/examples/icmp_responder/main.c index b820ad3b12d..5e78acd3537 100644 --- a/extras/libmemif/examples/icmp_responder/main.c +++ b/extras/libmemif/examples/icmp_responder/main.c @@ -225,7 +225,7 @@ icmpr_buffer_alloc (long n, uint16_t qid) int err; uint16_t r; /* set data pointer to shared memory and set buffer_len to shared mmeory buffer len */ - err = memif_buffer_alloc (c->conn, qid, c->tx_bufs, n, &r, 128); + err = memif_buffer_alloc (c->conn, qid, c->tx_bufs, n, &r, 0); if (err != MEMIF_ERR_SUCCESS) { INFO ("memif_buffer_alloc: %s", memif_strerror (err)); @@ -311,24 +311,25 @@ on_interrupt (memif_conn_handle_t conn, void *private_ctx, uint16_t qid) &(c->tx_bufs + i)->len, c->ip_addr); } + uint16_t fb; /* mark memif buffers and shared memory buffers as free */ - err = memif_refill_queue (c->conn, qid, rx); - c->rx_buf_num -= rx; + err = memif_refill_queue (c->conn, qid, rx, 0); + c->rx_buf_num -= fb; DBG ("freed %d buffers. %u/%u alloc/free buffers", - rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num); + fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num); icmpr_tx_burst (c->tx_qid); return 0; error: - err = memif_refill_queue (c->conn, qid, rx); + err = memif_refill_queue (c->conn, qid, rx, 0); if (err != MEMIF_ERR_SUCCESS) INFO ("memif_buffer_free: %s", memif_strerror (err)); - c->rx_buf_num -= rx; + c->rx_buf_num -= fb; DBG ("freed %d buffers. %u/%u alloc/free buffers", - rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num); + fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num); return 0; } |