Fix thresholds for increment_till_fail
[samplevnf.git] / VNFs / DPPD-PROX / packet_utils.c
index 7be978d..0189a1e 100644 (file)
@@ -46,7 +46,7 @@ static inline int find_ip(struct ether_hdr_arp *pkt, uint16_t len, uint32_t *ip_
 
        *vlan = 0;
        // Unstack VLAN tags
-       while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(prox_rte_vlan_hdr) < len)) {
+       while (((ether_type == ETYPE_VLAN) || (ether_type == ETYPE_8021ad)) && (l2_len + sizeof(prox_rte_vlan_hdr) < len)) {
                vlan_hdr = (prox_rte_vlan_hdr *)((uint8_t *)pkt + l2_len);
                l2_len +=4;
                ether_type = vlan_hdr->eth_proto;
@@ -100,40 +100,23 @@ static inline void find_vlan(struct ether_hdr_arp *pkt, uint16_t len, uint16_t *
 
 static inline struct ipv6_addr *find_ip6(prox_rte_ether_hdr *pkt, uint16_t len, struct ipv6_addr *ip_dst, uint16_t *vlan)
 {
-       prox_rte_vlan_hdr *vlan_hdr;
-       prox_rte_ipv6_hdr *ip;
        uint16_t ether_type = pkt->ether_type;
        uint16_t l2_len = sizeof(prox_rte_ether_hdr);
-
        *vlan = 0;
-       // Unstack VLAN tags
-       while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(prox_rte_vlan_hdr) < len)) {
-               vlan_hdr = (prox_rte_vlan_hdr *)((uint8_t *)pkt + l2_len);
-               l2_len +=4;
-               ether_type = vlan_hdr->eth_proto;
-               *vlan = rte_be_to_cpu_16(vlan_hdr->vlan_tci & 0xFF0F);  // Store VLAN, or CVLAN if QinQ
-       }
 
-       switch (ether_type) {
-       case ETYPE_MPLSU:
-       case ETYPE_MPLSM:
-               // In case of MPLS, next hop MAC is based on MPLS, not destination IP
-               l2_len = 0;
-               break;
-       case ETYPE_IPv4:
-       case ETYPE_EoGRE:
-       case ETYPE_ARP:
-               l2_len = 0;
-               break;
-       case ETYPE_IPv6:
-               break;
-       default:
-               l2_len = 0;
-               plog_warn("Unsupported packet type %x - CRC might be wrong\n", ether_type);
-               break;
+       if ((ether_type == ETYPE_VLAN) || (ether_type == ETYPE_8021ad)) {
+               prox_rte_vlan_hdr *vlan_hdr = (prox_rte_vlan_hdr *)((uint8_t *)pkt + l2_len);
+               ether_type = vlan_hdr->eth_proto;
+               l2_len +=4;
+               *vlan = rte_be_to_cpu_16(vlan_hdr->vlan_tci & 0xFF0F);
+               if (ether_type == ETYPE_VLAN) {
+                       vlan_hdr = (prox_rte_vlan_hdr *)(vlan_hdr + 1);
+                       ether_type = vlan_hdr->eth_proto;
+                       l2_len +=4;
+                       *vlan = rte_be_to_cpu_16(vlan_hdr->vlan_tci & 0xFF0F);
+               }
        }
-
-       if (l2_len && (l2_len + sizeof(prox_rte_ipv6_hdr) <= len)) {
+       if ((ether_type == ETYPE_IPv6) && (l2_len + sizeof(prox_rte_ipv6_hdr) <= len)) {
                prox_rte_ipv6_hdr *ip = (prox_rte_ipv6_hdr *)((uint8_t *)pkt + l2_len);
                // TODO: implement LPM => replace ip_dst by next hop IP DST
                memcpy(ip_dst, &ip->dst_addr, sizeof(struct ipv6_addr));
@@ -148,11 +131,11 @@ void send_unsollicited_neighbour_advertisement(struct task_base *tbase)
        uint8_t out = 0, port_id = tbase->l3.reachable_port_id;
        struct rte_mbuf *mbuf = NULL;
 
-       if (memcmp(&tbase->l3.local_ipv6, &null_addr, 16) != 0) {
+       if (*(__int128 *)(&tbase->l3.local_ipv6) != 0) {
                ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
                if (likely(ret == 0)) {
                        mbuf->port = port_id;
-                       build_neighbour_advertisement(tbase->l3.tmaster, mbuf, &prox_port_cfg[port_id].eth_addr, &tbase->l3.local_ipv6, PROX_UNSOLLICITED, prox_port_cfg[port_id].vlan_tag);
+                       build_neighbour_advertisement(tbase->l3.tmaster, mbuf, &prox_port_cfg[port_id].eth_addr, &tbase->l3.local_ipv6, PROX_UNSOLLICITED, prox_port_cfg[port_id].vlan_tags[0]);
                        tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out);
                        TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
                } else {
@@ -160,11 +143,11 @@ void send_unsollicited_neighbour_advertisement(struct task_base *tbase)
                        return;
                }
        }
-       if (memcmp(&tbase->l3.global_ipv6, &null_addr, 16) != 0) {
+       if (*(__int128 *)(&tbase->l3.global_ipv6) != 0) {
                ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
                if (likely(ret == 0)) {
                        mbuf->port = port_id;
-                       build_neighbour_advertisement(tbase->l3.tmaster, mbuf, &prox_port_cfg[port_id].eth_addr, &tbase->l3.global_ipv6, PROX_UNSOLLICITED, prox_port_cfg[port_id].vlan_tag);
+                       build_neighbour_advertisement(tbase->l3.tmaster, mbuf, &prox_port_cfg[port_id].eth_addr, &tbase->l3.global_ipv6, PROX_UNSOLLICITED, prox_port_cfg[port_id].vlan_tags[0]);
                        tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out);
                        TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
                } else {
@@ -186,7 +169,7 @@ static void send_router_sollicitation(struct task_base *tbase, struct task_args
        ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
        if (likely(ret == 0)) {
                mbuf->port = port_id;
-               build_router_sollicitation(mbuf, &prox_port_cfg[port_id].eth_addr, &targ->local_ipv6, prox_port_cfg[port_id].vlan_tag);
+               build_router_sollicitation(mbuf, &prox_port_cfg[port_id].eth_addr, &targ->local_ipv6, prox_port_cfg[port_id].vlan_tags[0]);
                tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out);
                TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
        } else {
@@ -365,14 +348,13 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
        return DROP_MBUF;
 }
 
-int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv6_addr *ip_dst, uint16_t *vlan)
+int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv6_addr *ip_dst, uint16_t *vlan, uint64_t tsc)
 {
        const uint64_t hz = rte_get_tsc_hz();
        prox_rte_ether_hdr *packet = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
        prox_rte_ether_addr *mac = &packet->d_addr;
        struct ipv6_addr *used_ip_src;
 
-       uint64_t tsc = rte_rdtsc();
        uint16_t len = rte_pktmbuf_pkt_len(mbuf);
 
        struct ipv6_addr *pkt_src_ip6;
@@ -383,33 +365,33 @@ int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv
        struct l3_base *l3 = &(tbase->l3);
 
        // Configure source IP
-       if (memcmp(&l3->local_ipv6, ip_dst, 8) == 0) {
+       if (*(uint64_t *)(&l3->local_ipv6) == *(uint64_t *)ip_dst) {
                // Same prefix as local -> use local
                used_ip_src = &l3->local_ipv6;
-       } else if (memcmp(&l3->global_ipv6 , ip_dst, 8) == 0) {
+       } else if (*(uint64_t *)(&l3->global_ipv6) == *(uint64_t *)ip_dst) {
                // Same prefix as global -> use global
                used_ip_src = &l3->global_ipv6;
-       } else if (memcmp(&l3->gw.ip6 , &null_addr, sizeof(struct ipv6_addr)) != 0) {
+       } else if (*(__int128 *)(&l3->gw.ip6) != 0) {
                used_ip_src = &l3->global_ipv6;
                memcpy(ip_dst, &l3->gw.ip6, sizeof(struct ipv6_addr));
-       } else if (memcmp(&l3->global_ipv6 , &null_addr, sizeof(struct ipv6_addr)) != 0) {
+       } else if (*(__int128 *)(&l3->global_ipv6) != 0) {
                // Global IP is defined -> use it
                used_ip_src = &l3->global_ipv6;
        } else {
                plog_info("Error as trying to send a packet to "IPv6_BYTES_FMT" using "IPv6_BYTES_FMT" (local)\n", IPv6_BYTES(ip_dst->bytes), IPv6_BYTES(l3->local_ipv6.bytes));
                return DROP_MBUF;
        }
-       memcpy(pkt_src_ip6, used_ip_src, sizeof(struct ipv6_addr));
+       rte_memcpy(pkt_src_ip6, used_ip_src, sizeof(struct ipv6_addr));
 
        // Configure dst mac
        if (likely(l3->n_pkts < 4)) {
                for (unsigned int idx = 0; idx < l3->n_pkts; idx++) {
-                       if (memcmp(ip_dst, &l3->optimized_arp_table[idx].ip6, sizeof(struct ipv6_addr)) == 0) {
+                       if (*(__int128 *)ip_dst == *(__int128 *)(&l3->optimized_arp_table[idx].ip6)) {
                                 // IP address already in table
                                if ((tsc < l3->optimized_arp_table[idx].arp_ndp_retransmit_timeout) && (tsc < l3->optimized_arp_table[idx].reachable_timeout)) {
                                        // MAC address was recently updated in table, use it
                                        // plog_dbg("Valid MAC address found => send packet\n");
-                                       memcpy(mac, &l3->optimized_arp_table[idx].mac, sizeof(prox_rte_ether_addr));
+                                       rte_memcpy(mac, &l3->optimized_arp_table[idx].mac, sizeof(prox_rte_ether_addr));
                                        return SEND_MBUF;
                                } else if (tsc > l3->optimized_arp_table[idx].arp_ndp_retransmit_timeout) {
                                        // NDP not sent since a long time, send NDP
@@ -558,26 +540,28 @@ void task_start_l3(struct task_base *tbase, struct task_args *targ)
         if (port && (tbase->l3.arp_nd_pool == NULL)) {
                static char name[] = "arp0_pool";
                 tbase->l3.reachable_port_id = port - prox_port_cfg;
-               if ((targ->local_ipv4 && port->ip) && (targ->local_ipv4 != port->ip)) {
-                       PROX_PANIC(1, "local_ipv4 in core section ("IPv4_BYTES_FMT") differs from port section ("IPv4_BYTES_FMT")\n", IP4(rte_be_to_cpu_32(targ->local_ipv4)), IP4(rte_be_to_cpu_32(port->ip)));
+               if ((targ->local_ipv4 && port->ip_addr[0].ip) && (targ->local_ipv4 != port->ip_addr[0].ip)) {
+                       PROX_PANIC(1, "local_ipv4 in core section ("IPv4_BYTES_FMT") differs from port section ("IPv4_BYTES_FMT")\n", IP4(rte_be_to_cpu_32(targ->local_ipv4)), IP4(rte_be_to_cpu_32(port->ip_addr[0].ip)));
                }
-               if ((targ->local_ipv4 && port->ip) && (targ->local_prefix != port->prefix)) {
-                       PROX_PANIC(1, "local_ipv4 prefix in core section (%d) differs from port section (%d)\n", targ->local_prefix, port->prefix);
+               if ((targ->local_ipv4 && port->ip_addr[0].ip) && (targ->local_prefix != port->ip_addr[0].prefix)) {
+                       PROX_PANIC(1, "local_ipv4 prefix in core section (%d) differs from port section (%d)\n", targ->local_prefix, port->ip_addr[0].prefix);
                }
-               if (!targ->local_ipv4) {
-                       targ->local_ipv4 = port->ip;
-                       targ->local_prefix = port->prefix;
-                       plog_info("Setting core local_ipv4 from port %d local_ipv4 to "IPv4_BYTES_FMT"\n", tbase->l3.reachable_port_id, IP4(rte_be_to_cpu_32(port->ip)));
+               if (!port->ip_addr[0].ip && targ->local_ipv4) {
+                       port->ip_addr[0].ip = targ->local_ipv4;
+                       port->ip_addr[0].prefix = targ->local_prefix;
+                       port->n_vlans = 1;
+                       port->vlan_tags[0] = 0;
+                       plog_info("Setting port local_ipv4 from core %d local_ipv4 to "IPv4_BYTES_FMT"\n", tbase->l3.reachable_port_id, IP4(rte_be_to_cpu_32(port->ip_addr[0].ip)));
                }
-               if (targ->local_ipv4) {
-                       tbase->l3.local_ipv4 = rte_be_to_cpu_32(targ->local_ipv4);
-                       register_ip_to_ctrl_plane(tbase->l3.tmaster, tbase->l3.local_ipv4, tbase->l3.reachable_port_id, targ->lconf->id, targ->id);
+               for (int vlan_id = 0; vlan_id < port->n_vlans; vlan_id++) {
+                       if (port->ip_addr[vlan_id].ip)
+                               register_ip_to_ctrl_plane(tbase->l3.tmaster, rte_be_to_cpu_32(port->ip_addr[vlan_id].ip), tbase->l3.reachable_port_id, targ->lconf->id, targ->id);
                }
                if (strcmp(targ->route_table, "") != 0) {
                        struct lpm4 *lpm;
                        int ret;
 
-                       PROX_PANIC(tbase->l3.local_ipv4 == 0, "missing local_ipv4 while route table is specified in L3 mode\n");
+                       PROX_PANIC(port->n_vlans == 0, "missing local_ipv4 while route table is specified in L3 mode\n");
 
                        // LPM might be modified runtime => do not share with other cores
                        ret = lua_to_lpm4(prox_lua(), GLOBAL, targ->route_table, socket_id, &lpm);
@@ -600,10 +584,13 @@ void task_start_l3(struct task_base *tbase, struct task_args *targ)
                        }
                        plog_info("Using routing table %s in l3 mode, with %d gateways\n", targ->route_table, tbase->l3.nb_gws);
 
-                       // Last but one "next_hop_index" is not a gateway but direct routes
-                       tbase->l3.next_hops[tbase->l3.nb_gws].ip = 0;
-                       ret = rte_lpm_add(tbase->l3.ipv4_lpm, targ->local_ipv4, targ->local_prefix, tbase->l3.nb_gws++);
-                       PROX_PANIC(ret, "Failed to add local_ipv4 "IPv4_BYTES_FMT"/%d to lpm\n", IP4(tbase->l3.local_ipv4), targ->local_prefix);
+                       // Last but one (x n_vlans) "next_hop_index" is not a gateway but direct routes
+                       for (int vlan_id = 0; vlan_id < port->n_vlans; vlan_id++) {
+                               tbase->l3.next_hops[tbase->l3.nb_gws].ip = 0;
+                               ret = rte_lpm_add(tbase->l3.ipv4_lpm, port->ip_addr[vlan_id].ip, port->ip_addr[vlan_id].prefix, tbase->l3.nb_gws++);
+                               PROX_PANIC(ret, "Failed to add local_ipv4 "IPv4_BYTES_FMT"/%d to lpm\n", IP4(port->ip_addr[vlan_id].ip), port->ip_addr[vlan_id].prefix);
+                       }
+
                        // Last "next_hop_index" is default gw
                        tbase->l3.next_hops[tbase->l3.nb_gws].ip = rte_bswap32(targ->gateway_ipv4);
                        if (targ->gateway_ipv4) {
@@ -666,11 +653,6 @@ void task_set_gateway_ip(struct task_base *tbase, uint32_t ip)
        tbase->flags &= ~FLAG_DST_MAC_KNOWN;
 }
 
-void task_set_local_ip(struct task_base *tbase, uint32_t ip)
-{
-       tbase->l3.local_ipv4 = ip;
-}
-
 static void reset_arp_ndp_retransmit_timeout(struct l3_base *l3, uint32_t ip)
 {
        uint32_t idx;