diff options
Diffstat (limited to 'VNFs/DPPD-PROX/handle_swap.c')
-rw-r--r-- | VNFs/DPPD-PROX/handle_swap.c | 245 |
1 files changed, 231 insertions, 14 deletions
diff --git a/VNFs/DPPD-PROX/handle_swap.c b/VNFs/DPPD-PROX/handle_swap.c index 457c2fac..503af598 100644 --- a/VNFs/DPPD-PROX/handle_swap.c +++ b/VNFs/DPPD-PROX/handle_swap.c @@ -1,5 +1,5 @@ /* -// Copyright (c) 2010-2017 Intel Corporation +// Copyright (c) 2010-2020 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ #include <rte_mbuf.h> #include <rte_udp.h> +#include <rte_icmp.h> #include "task_init.h" #include "task_base.h" @@ -26,46 +27,65 @@ #include "qinq.h" #include "gre.h" #include "prefetch.h" +#include "defines.h" #include "igmp.h" #include "prox_cksum.h" #include "prox_compat.h" +#define MAX_STORE_PKT_SIZE 2048 + +struct packet { + unsigned int len; + unsigned char buf[MAX_STORE_PKT_SIZE]; +}; + struct task_swap { struct task_base base; struct rte_mempool *igmp_pool; + uint32_t flags; uint32_t runtime_flags; uint32_t igmp_address; uint8_t src_dst_mac[12]; uint32_t local_ipv4; int offload_crc; + uint64_t last_echo_req_rcvd_tsc; + uint64_t last_echo_rep_rcvd_tsc; + uint32_t n_echo_req; + uint32_t n_echo_rep; + uint32_t store_pkt_id; + uint32_t store_msk; + struct packet *store_buf; + FILE *fp; }; #define NB_IGMP_MBUF 1024 #define IGMP_MBUF_SIZE 2048 #define NB_CACHE_IGMP_MBUF 256 +#define GENEVE_PORT 0xc117 // in be + static void write_src_and_dst_mac(struct task_swap *task, struct rte_mbuf *mbuf) { prox_rte_ether_hdr *hdr; prox_rte_ether_addr mac; - if (unlikely((task->runtime_flags & (TASK_ARG_DST_MAC_SET|TASK_ARG_SRC_MAC_SET)) == (TASK_ARG_DST_MAC_SET|TASK_ARG_SRC_MAC_SET))) { + if (unlikely((task->flags & (TASK_ARG_DST_MAC_SET|TASK_ARG_SRC_MAC_SET)) == (TASK_ARG_DST_MAC_SET|TASK_ARG_SRC_MAC_SET))) { /* Source and Destination mac hardcoded */ hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *); rte_memcpy(hdr, task->src_dst_mac, sizeof(task->src_dst_mac)); } else { hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *); - if (likely((task->runtime_flags & TASK_ARG_SRC_MAC_SET) == 0)) { + if (unlikely((task->flags & TASK_ARG_SRC_MAC_SET) == 0)) { /* dst mac will be used as src mac */ prox_rte_ether_addr_copy(&hdr->d_addr, &mac); } - if (unlikely(task->runtime_flags & TASK_ARG_DST_MAC_SET)) + if (unlikely(task->flags & TASK_ARG_DST_MAC_SET)) prox_rte_ether_addr_copy((prox_rte_ether_addr *)&task->src_dst_mac[0], &hdr->d_addr); else prox_rte_ether_addr_copy(&hdr->s_addr, &hdr->d_addr); - if (unlikely(task->runtime_flags & TASK_ARG_SRC_MAC_SET)) { + if (likely(task->flags & TASK_ARG_SRC_MAC_SET)) { prox_rte_ether_addr_copy((prox_rte_ether_addr *)&task->src_dst_mac[6], &hdr->s_addr); } else { prox_rte_ether_addr_copy(&mac, &hdr->s_addr); @@ -79,6 +99,21 @@ static inline void build_mcast_mac(uint32_t ip, prox_rte_ether_addr *dst_mac) memcpy(dst_mac, &mac, sizeof(prox_rte_ether_addr)); } +static inline void build_icmp_reply_message(struct task_base *tbase, struct rte_mbuf *mbuf) +{ + struct task_swap *task = (struct task_swap *)tbase; + prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *); + prox_rte_ether_addr dst_mac; + prox_rte_ether_addr_copy(&hdr->s_addr, &dst_mac); + prox_rte_ether_addr_copy(&hdr->d_addr, &hdr->s_addr); + prox_rte_ether_addr_copy(&dst_mac, &hdr->d_addr); + prox_rte_ipv4_hdr *ip_hdr = (prox_rte_ipv4_hdr *)(hdr + 1); + ip_hdr->dst_addr = ip_hdr->src_addr; + ip_hdr->src_addr = task->local_ipv4; + prox_rte_icmp_hdr *picmp = (prox_rte_icmp_hdr *)(ip_hdr + 1); + picmp->icmp_type = PROX_RTE_IP_ICMP_ECHO_REPLY; +} + static inline void build_igmp_message(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t ip, uint8_t igmp_message) { struct task_swap *task = (struct task_swap *)tbase; @@ -113,6 +148,70 @@ static inline void build_igmp_message(struct task_base *tbase, struct rte_mbuf * prox_ip_udp_cksum(mbuf, ip_hdr, sizeof(prox_rte_ether_hdr), sizeof(prox_rte_ipv4_hdr), task->offload_crc); } +static void stop_swap(struct task_base *tbase) +{ + uint32_t i, j; + struct task_swap *task = (struct task_swap *)tbase; + + if (task->igmp_pool) { + rte_mempool_free(task->igmp_pool); + task->igmp_pool = NULL; + } + + if (task->store_msk) { + for (i = task->store_pkt_id & task->store_msk; i < task->store_msk + 1; i++) { + if (task->store_buf[i].len) { + fprintf(task->fp, "%06d: ", i); + for (j = 0; j < task->store_buf[i].len; j++) { + fprintf(task->fp, "%02x ", task->store_buf[i].buf[j]); + } + fprintf(task->fp, "\n"); + } + } + for (i = 0; i < (task->store_pkt_id & task->store_msk); i++) { + if (task->store_buf[i].len) { + fprintf(task->fp, "%06d: ", i); + for (j = 0; j < task->store_buf[i].len; j++) { + fprintf(task->fp, "%02x ", task->store_buf[i].buf[j]); + } + fprintf(task->fp, "\n"); + } + } + } +} + +static void handle_ipv6(struct task_swap *task, struct rte_mbuf *mbufs, prox_rte_ipv6_hdr *ipv6_hdr, uint8_t *out) +{ + __m128i ip = _mm_loadu_si128((__m128i*)&(ipv6_hdr->src_addr)); + uint16_t port; + uint16_t payload_len; + prox_rte_udp_hdr *udp_hdr; + + rte_mov16((uint8_t *)&(ipv6_hdr->src_addr), (uint8_t *)&(ipv6_hdr->dst_addr)); // Copy dst into src + rte_mov16((uint8_t *)&(ipv6_hdr->dst_addr), (uint8_t *)&ip); // Copy src into dst + switch(ipv6_hdr->proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + payload_len = ipv6_hdr->payload_len; + udp_hdr = (prox_rte_udp_hdr *)(ipv6_hdr + 1); + if (unlikely(udp_hdr->dgram_len < payload_len)) { + plog_warn("Unexpected L4 len (%u) versus L3 payload len (%u) in IPv6 packet\n", udp_hdr->dgram_len, payload_len); + *out = OUT_DISCARD; + break; + } + port = udp_hdr->dst_port; + udp_hdr->dst_port = udp_hdr->src_port; + udp_hdr->src_port = port; + write_src_and_dst_mac(task, mbufs); + *out = 0; + break; + default: + plog_warn("Unsupported next hop %u in IPv6 packet\n", ipv6_hdr->proto); + *out = OUT_DISCARD; + break; + } +} + static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts) { struct task_swap *task = (struct task_swap *)tbase; @@ -120,6 +219,7 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui prox_rte_ether_addr mac; prox_rte_ipv4_hdr *ip_hdr; prox_rte_udp_hdr *udp_hdr; + prox_rte_ipv6_hdr *ipv6_hdr; struct gre_hdr *pgre; prox_rte_ipv4_hdr *inner_ip_hdr; uint32_t ip; @@ -131,7 +231,11 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui prox_rte_vlan_hdr *vlan; uint16_t j; struct igmpv2_hdr *pigmp; + prox_rte_icmp_hdr *picmp; uint8_t type; + static int llc_printed = 0; + static int lldp_printed = 0; + static int geneve_printed = 0; for (j = 0; j < n_pkts; ++j) { PREFETCH0(mbufs[j]); @@ -153,6 +257,11 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui } mpls_len += sizeof(struct mpls_hdr); ip_hdr = (prox_rte_ipv4_hdr *)(mpls + 1); + if (unlikely((ip_hdr->version_ihl >> 4) == 6)) { + ipv6_hdr = (prox_rte_ipv6_hdr *)(ip_hdr); + handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]); + continue; + } break; case ETYPE_8021ad: qinq = (struct qinq_hdr *)hdr; @@ -161,20 +270,34 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui out[j] = OUT_DISCARD; continue; } - ip_hdr = (prox_rte_ipv4_hdr *)(qinq + 1); + if (qinq->ether_type == ETYPE_IPv4) { + ip_hdr = (prox_rte_ipv4_hdr *)(qinq + 1); + } else if (qinq->ether_type == ETYPE_IPv6) { + ipv6_hdr = (prox_rte_ipv6_hdr *)(qinq + 1); + handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]); + continue; + } else { + plog_warn("Unsupported packet type\n"); + out[j] = OUT_DISCARD; + continue; + } break; case ETYPE_VLAN: vlan = (prox_rte_vlan_hdr *)(hdr + 1); if (vlan->eth_proto == ETYPE_IPv4) { ip_hdr = (prox_rte_ipv4_hdr *)(vlan + 1); + } else if (vlan->eth_proto == ETYPE_IPv6) { + ipv6_hdr = (prox_rte_ipv6_hdr *)(vlan + 1); + handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]); + continue; } else if (vlan->eth_proto == ETYPE_VLAN) { vlan = (prox_rte_vlan_hdr *)(vlan + 1); if (vlan->eth_proto == ETYPE_IPv4) { ip_hdr = (prox_rte_ipv4_hdr *)(vlan + 1); } else if (vlan->eth_proto == ETYPE_IPv6) { - plog_warn("Unsupported IPv6\n"); - out[j] = OUT_DISCARD; + ipv6_hdr = (prox_rte_ipv6_hdr *)(vlan + 1); + handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]); continue; } else { @@ -192,19 +315,47 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui ip_hdr = (prox_rte_ipv4_hdr *)(hdr + 1); break; case ETYPE_IPv6: - plog_warn("Unsupported IPv6\n"); - out[j] = OUT_DISCARD; + ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr + 1); + handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]); continue; case ETYPE_LLDP: + if (!lldp_printed) { + plog_info("Discarding LLDP packets (only printed once)\n"); + lldp_printed = 1; + } out[j] = OUT_DISCARD; continue; default: + if ((rte_bswap16(hdr->ether_type) < 0x600) && (rte_bswap16(hdr->ether_type) >= 16)) { + // 802.3 + struct prox_llc { + uint8_t dsap; + uint8_t lsap; + uint8_t control; + }; + struct prox_llc *llc = (struct prox_llc *)(hdr + 1); + if ((llc->dsap == 0x42) && (llc->lsap == 0x42)) { + // STP Protocol + out[j] = OUT_DISCARD; + if (!llc_printed) { + plog_info("Discarding STP packets (only printed once)\n"); + llc_printed = 1; + } + continue; + } + } plog_warn("Unsupported ether_type 0x%x\n", hdr->ether_type); out[j] = OUT_DISCARD; continue; } // TODO 2 : check packet is long enough for Ethernet + IP + UDP + extra header (VLAN, MPLS, ...) + // IPv4 packet + ip = ip_hdr->dst_addr; + if (unlikely((ip_hdr->version_ihl >> 4) != 4)) { + out[j] = OUT_DISCARD; + continue; + } switch (ip_hdr->next_proto_id) { case IPPROTO_GRE: @@ -226,19 +377,61 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui break; case IPPROTO_UDP: case IPPROTO_TCP: - if (task->igmp_address && PROX_RTE_IS_IPV4_MCAST(rte_be_to_cpu_32(ip))) { + if (unlikely(task->igmp_address && PROX_RTE_IS_IPV4_MCAST(rte_be_to_cpu_32(ip)))) { out[j] = OUT_DISCARD; continue; } udp_hdr = (prox_rte_udp_hdr *)(ip_hdr + 1); + port = udp_hdr->dst_port; ip_hdr->dst_addr = ip_hdr->src_addr; ip_hdr->src_addr = ip; - port = udp_hdr->dst_port; + if ((port == GENEVE_PORT) && (task->runtime_flags & TASK_DO_NOT_FWD_GENEVE)) { + if (!geneve_printed) { + plog_info("Discarding geneve (only printed once)\n"); + geneve_printed = 1; + } + out[j] = OUT_DISCARD; + continue; + } + udp_hdr->dst_port = udp_hdr->src_port; udp_hdr->src_port = port; write_src_and_dst_mac(task, mbufs[j]); break; + case IPPROTO_ICMP: + picmp = (prox_rte_icmp_hdr *)(ip_hdr + 1); + type = picmp->icmp_type; + if (type == PROX_RTE_IP_ICMP_ECHO_REQUEST) { + if (ip_hdr->dst_addr == task->local_ipv4) { + task->n_echo_req++; + if (rte_rdtsc() - task->last_echo_req_rcvd_tsc > rte_get_tsc_hz()) { + plog_info("Received %u Echo Request on IP "IPv4_BYTES_FMT" (last received from IP "IPv4_BYTES_FMT")\n", task->n_echo_req, IPv4_BYTES(((uint8_t*)&ip_hdr->dst_addr)), IPv4_BYTES(((uint8_t*)&ip_hdr->src_addr))); + task->n_echo_req = 0; + task->last_echo_req_rcvd_tsc = rte_rdtsc(); + } + build_icmp_reply_message(tbase, mbufs[j]); + } else { + out[j] = OUT_DISCARD; + continue; + } + } else if (type == PROX_RTE_IP_ICMP_ECHO_REPLY) { + if (ip_hdr->dst_addr == task->local_ipv4) { + task->n_echo_rep++; + if (rte_rdtsc() - task->last_echo_rep_rcvd_tsc > rte_get_tsc_hz()) { + plog_info("Received %u Echo Reply on IP "IPv4_BYTES_FMT" (last received from IP "IPv4_BYTES_FMT")\n", task->n_echo_rep, IPv4_BYTES(((uint8_t*)&ip_hdr->dst_addr)), IPv4_BYTES(((uint8_t*)&ip_hdr->src_addr))); + task->n_echo_rep = 0; + task->last_echo_rep_rcvd_tsc = rte_rdtsc(); + } + } else { + out[j] = OUT_DISCARD; + continue; + } + } else { + out[j] = OUT_DISCARD; + continue; + } + break; case IPPROTO_IGMP: pigmp = (struct igmpv2_hdr *)(ip_hdr + 1); // TODO: check packet len @@ -271,6 +464,16 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui continue; } } + if (task->store_msk) { + for (int i = 0; i < n_pkts; i++) { + if (out[i] != OUT_DISCARD) { + hdr = rte_pktmbuf_mtod(mbufs[i], prox_rte_ether_hdr *); + memcpy(&task->store_buf[task->store_pkt_id & task->store_msk].buf, hdr, rte_pktmbuf_pkt_len(mbufs[i])); + task->store_buf[task->store_pkt_id & task->store_msk].len = rte_pktmbuf_pkt_len(mbufs[i]); + task->store_pkt_id++; + } + } + } return task->base.tx_pkt(&task->base, mbufs, n_pkts, out); } @@ -350,7 +553,8 @@ static void init_task_swap(struct task_base *tbase, struct task_args *targ) plog_info("\t\tCore %d: src mac set from port\n", targ->lconf->id); } } - task->runtime_flags = targ->flags; + task->flags = targ->flags; + task->runtime_flags = targ->runtime_flags; task->igmp_address = rte_cpu_to_be_32(targ->igmp_address); if (task->igmp_pool == NULL) { static char name[] = "igmp0_pool"; @@ -368,7 +572,19 @@ static void init_task_swap(struct task_base *tbase, struct task_args *targ) struct prox_port_cfg *port = find_reachable_port(targ); if (port) { - task->offload_crc = port->requested_tx_offload & (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM); + task->offload_crc = port->requested_tx_offload & (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | RTE_ETH_TX_OFFLOAD_UDP_CKSUM); + } + task->store_pkt_id = 0; + if (targ->store_max) { + char filename[256]; + sprintf(filename, "swap_buf_%02d_%02d", targ->lconf->id, targ->task); + + task->store_msk = targ->store_max - 1; + task->store_buf = (struct packet *)malloc(sizeof(struct packet) * targ->store_max); + task->fp = fopen(filename, "w+"); + PROX_PANIC(task->fp == NULL, "Unable to open %s\n", filename); + } else { + task->store_msk = 0; } } @@ -378,6 +594,7 @@ static struct task_init task_init_swap = { .handle = handle_swap_bulk, .flag_features = 0, .size = sizeof(struct task_swap), + .stop_last = stop_swap }; __attribute__((constructor)) static void reg_task_swap(void) |