diff options
Diffstat (limited to 'VNFs/DPPD-PROX/packet_utils.c')
-rw-r--r-- | VNFs/DPPD-PROX/packet_utils.c | 170 |
1 files changed, 100 insertions, 70 deletions
diff --git a/VNFs/DPPD-PROX/packet_utils.c b/VNFs/DPPD-PROX/packet_utils.c index 9832a039..95ce7abc 100644 --- a/VNFs/DPPD-PROX/packet_utils.c +++ b/VNFs/DPPD-PROX/packet_utils.c @@ -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; @@ -81,11 +81,11 @@ static inline int find_ip(struct ether_hdr_arp *pkt, uint16_t len, uint32_t *ip_ return -1; } -static inline struct ipv6_addr *find_ip6(prox_rte_ether_hdr *pkt, uint16_t len, struct ipv6_addr *ip_dst, uint16_t *vlan) +static inline void find_vlan(struct ether_hdr_arp *pkt, uint16_t len, uint16_t *vlan) { prox_rte_vlan_hdr *vlan_hdr; - prox_rte_ipv6_hdr *ip; - uint16_t ether_type = pkt->ether_type; + prox_rte_ether_hdr *eth_hdr = (prox_rte_ether_hdr*)pkt; + uint16_t ether_type = eth_hdr->ether_type; uint16_t l2_len = sizeof(prox_rte_ether_hdr); *vlan = 0; @@ -94,29 +94,29 @@ static inline struct ipv6_addr *find_ip6(prox_rte_ether_hdr *pkt, uint16_t 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 + *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; - } +static inline struct ipv6_addr *find_ip6(prox_rte_ether_hdr *pkt, uint16_t len, struct ipv6_addr *ip_dst, uint16_t *vlan) +{ + uint16_t ether_type = pkt->ether_type; + uint16_t l2_len = sizeof(prox_rte_ether_hdr); + *vlan = 0; - if (l2_len && (l2_len + sizeof(prox_rte_ipv6_hdr) <= len)) { + 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 ((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)); @@ -125,20 +125,38 @@ static inline struct ipv6_addr *find_ip6(prox_rte_ether_hdr *pkt, uint16_t len, return NULL; } -static void send_unsollicited_neighbour_advertisement(struct task_base *tbase, struct task_args *targ) +void send_unsollicited_neighbour_advertisement(struct task_base *tbase) { int ret; uint8_t out = 0, port_id = tbase->l3.reachable_port_id; - struct rte_mbuf *mbuf; - - 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, &targ->local_ipv6, PROX_UNSOLLICITED); - tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out); - TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1); - } else { - plog_err("Failed to get a mbuf from arp/ndp mempool\n"); + struct rte_mbuf *mbuf = NULL; + + 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_tags[0]); + tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out); + TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1); + } else { + plog_err("Failed to get a mbuf from arp/ndp mempool\n"); + return; + } + } + 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_tags[0]); + tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out); + TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1); + } else { + plog_err("Failed to get a mbuf from arp/ndp mempool\n"); + return; + } + } + if (mbuf == NULL) { + plog_err("No neighbor advertisement sent as no local or global ipv6\n"); } } @@ -151,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); + 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 { @@ -253,7 +271,10 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d } // No Routing table specified: only a local ip and maybe a gateway // Old default behavior: if a gw is specified, ALL packets go to this gateway (even those we could send w/o the gw + + uint16_t len = rte_pktmbuf_pkt_len(mbuf); if (l3->gw.ip) { + find_vlan(packet, len, vlan); if (likely((l3->flags & FLAG_DST_MAC_KNOWN) && (tsc < l3->gw.arp_ndp_retransmit_timeout) && (tsc < l3->gw.reachable_timeout))) { memcpy(mac, &l3->gw.mac, sizeof(prox_rte_ether_addr)); return SEND_MBUF; @@ -278,7 +299,6 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d } } - uint16_t len = rte_pktmbuf_pkt_len(mbuf); if (find_ip(packet, len, ip_dst, vlan) != 0) { // Unable to find IP address => non IP packet => send it as it return SEND_MBUF; @@ -328,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; @@ -344,26 +363,35 @@ int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv return SEND_MBUF; } struct l3_base *l3 = &(tbase->l3); - if (memcmp(&l3->local_ipv6, ip_dst, 8) == 0) { + + // Configure source IP + 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 , &null_addr, 16) != 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 (*(__int128 *)(&l3->gw.ip6) != 0) { + used_ip_src = &l3->global_ipv6; + memcpy(ip_dst, &l3->gw.ip6, sizeof(struct ipv6_addr)); + } 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; } + rte_memcpy(pkt_src_ip6, used_ip_src, sizeof(struct ipv6_addr)); - 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 @@ -464,27 +492,29 @@ void task_init_l3(struct task_base *tbase, struct task_args *targ) .key_len = sizeof(uint32_t), .hash_func = rte_hash_crc, .hash_func_init_val = 0, + .socket_id = socket_id, }; if (targ->flags & TASK_ARG_L3) { - plog_info("\tInitializing L3 (IPv4)\n"); + plog_info("\t\tInitializing L3 (IPv4)\n"); tbase->l3.ip_hash = rte_hash_create(&hash_params); PROX_PANIC(tbase->l3.ip_hash == NULL, "Failed to set up ip hash table\n"); hash_name[0]++; } if (targ->flags & TASK_ARG_NDP) { - plog_info("\tInitializing NDP (IPv6)\n"); + plog_info("\t\tInitializing NDP (IPv6)\n"); hash_params.key_len = sizeof(struct ipv6_addr); tbase->l3.ip6_hash = rte_hash_create(&hash_params); PROX_PANIC(tbase->l3.ip6_hash == NULL, "Failed to set up ip hash table\n"); } tbase->l3.arp_table = (struct arp_table *)prox_zmalloc(n_entries * sizeof(struct arp_table), socket_id); PROX_PANIC(tbase->l3.arp_table == NULL, "Failed to allocate memory for %u entries in arp/ndp table\n", n_entries); - plog_info("\tarp/ndp table, with %d entries of size %ld\n", n_entries, sizeof(struct l3_base)); + plog_info("\t\tarp/ndp table, with %d entries of size %ld\n", n_entries, sizeof(struct l3_base)); targ->lconf->ctrl_func_p[targ->task] = handle_ctrl_plane_pkts; targ->lconf->ctrl_timeout = freq_to_tsc(targ->ctrl_freq); tbase->l3.gw.ip = rte_cpu_to_be_32(targ->gateway_ipv4); + memcpy(&tbase->l3.gw.ip6, &targ->gateway_ipv6, sizeof(struct ipv6_addr)); tbase->flags |= TASK_L3; tbase->l3.core_id = targ->lconf->id; tbase->l3.task_id = targ->id; @@ -511,26 +541,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); @@ -553,10 +585,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) { @@ -569,7 +604,7 @@ void task_start_l3(struct task_base *tbase, struct task_args *targ) // Create IPv6 addr if none were configured if (targ->flags & TASK_ARG_NDP) { - if (!memcmp(&targ->local_ipv6, &null_addr, 16)) { + if (!memcmp(&targ->local_ipv6, &null_addr, sizeof(struct ipv6_addr))) { set_link_local(&targ->local_ipv6); set_EUI(&targ->local_ipv6, &port->eth_addr); } @@ -607,7 +642,7 @@ void task_start_l3(struct task_base *tbase, struct task_args *targ) } if ((targ->flags & TASK_ARG_NDP) && (targ->flags & TASK_ARG_SEND_NA_AT_STARTUP)) { plog_info("Sending unsollicited Neighbour Advertisement\n"); - send_unsollicited_neighbour_advertisement(tbase, targ); + send_unsollicited_neighbour_advertisement(tbase); } } @@ -619,11 +654,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; |