/* // Copyright (c) 2017 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ /* * Filename - l2_proto.c * L2 Protocol Handler */ #include "l2_proto.h" static struct proto_packet_type *proto_list[3]; /* * Function to register the rx functions for different ethertypes. This is maintained in a list. */ void list_add_type(uint16_t type, void (*func) (struct rte_mbuf **, uint16_t, uint64_t, l2_phy_interface_t *)) { if (type == ETHER_TYPE_IPv4) { proto_list[IPv4_VAL] = rte_malloc(NULL, sizeof(struct proto_packet_type), RTE_CACHE_LINE_SIZE); proto_list[IPv4_VAL]->type = type; proto_list[IPv4_VAL]->func = func; } else if (type == ETHER_TYPE_ARP) { proto_list[ARP_VAL] = rte_malloc(NULL, sizeof(struct proto_packet_type), RTE_CACHE_LINE_SIZE); proto_list[ARP_VAL]->type = type; proto_list[ARP_VAL]->func = func; } else if (type == ETHER_TYPE_IPv6) { proto_list[IPv6_VAL] = rte_malloc(NULL, sizeof(struct proto_packet_type), RTE_CACHE_LINE_SIZE); proto_list[IPv6_VAL]->type = type; proto_list[IPv6_VAL]->func = func; } } /* * Check the mac address to see whether it is destined to this host or not. * Call relevant functions registered by other modules when the ethertype matches, * if it is destined to this host. Drop the packet otherwise. */ void l2_check_mac(struct rte_mbuf *m[IFM_BURST_SIZE], l2_phy_interface_t *port, uint8_t i, uint64_t *pkts_mask, uint64_t *arp_pkts_mask, uint64_t *ipv4_pkts_mask, uint64_t *ipv6_pkts_mask) { struct ether_hdr *eth=NULL; uint16_t same_mac=0; uint16_t ethtype = 0; if (m[i] != NULL) { eth = rte_pktmbuf_mtod(m[i], struct ether_hdr *); if(eth) ethtype = rte_be_to_cpu_16(eth->ether_type); if (eth == NULL) { /*Destination MAC address inside the packet */ printf("l2_check_mac: Ethernet Dest Addr NULL !!!\n"); return; } ethtype = rte_be_to_cpu_16(eth->ether_type); #if L2_PROTO_DBG printf("%s => mbuf pkt dest mac addr: %x:%x:%x:%x:%x:%x\n", __FUNCTION__, eth->d_addr.addr_bytes[0], eth->d_addr.addr_bytes[1], eth->d_addr.addr_bytes[2], eth->d_addr.addr_bytes[3], eth->d_addr.addr_bytes[4], eth->d_addr.addr_bytes[5]); printf("%s => port mac addr: %x:%x:%x:%x:%x:%x\n", __FUNCTION__, port->macaddr[0], port->macaddr[1], port->macaddr[2], port->macaddr[3], port->macaddr[4], port->macaddr[5]); #endif /* Compare the mac addresses */ same_mac = (is_same_ether_addr (ð->d_addr, (struct ether_addr *)port->macaddr) || ((is_broadcast_ether_addr ((struct ether_addr *)ð->d_addr) && (ethtype == ETHER_TYPE_ARP))) || (ethtype == ETHER_TYPE_IPv6 && eth->d_addr.addr_bytes[0] == 0x33 && eth->d_addr.addr_bytes[1] == 0x33)); if (!same_mac) { uint64_t temp_mask = 1LLU << i; *pkts_mask ^= temp_mask; rte_pktmbuf_free(m[i]); m[i] = NULL; } else if ((ethtype == ETHER_TYPE_IPv4) && same_mac) { uint64_t temp_mask = 1LLU << i; *ipv4_pkts_mask ^= temp_mask; } else if ((ethtype == ETHER_TYPE_ARP) && same_mac) { uint64_t temp_mask = 1LLU << i; *arp_pkts_mask ^= temp_mask; } else if ((ethtype == ETHER_TYPE_IPv6) && same_mac) { uint64_t temp_mask = 1LLU << i; *ipv6_pkts_mask ^= temp_mask; } } printf("\n%s: arp_pkts_mask = %" PRIu64 ", ipv4_pkts_mask = %" PRIu64 ", ipv6_pkts_mask =%" PRIu64 ", pkt-type = %x, sam_mac = %d\n", __FUNCTION__, *arp_pkts_mask, *ipv4_pkts_mask, *ipv6_pkts_mask, ethtype, same_mac); } void protocol_handler_recv(struct rte_mbuf **pkts_burst, uint16_t nb_rx, l2_phy_interface_t *port) { uint8_t i; uint64_t pkts_mask = 0; //RTE_LEN2MASK(nb_rx, uint64_t); uint64_t arp_pkts_mask = 0; //RTE_LEN2MASK(nb_rx, uint64_t); uint64_t ipv4_pkts_mask = 0; //RTE_LEN2MASK(nb_rx, uint64_t); uint64_t ipv6_pkts_mask = 0; //RTE_LEN2MASK(nb_rx, uint64_t); /*Check the mac address of every single packet and unset the bits in the packet mask *for those packets which are not destined to this host */ for (i = 0; i < nb_rx; i++) { l2_check_mac(pkts_burst, port, i, &pkts_mask, &arp_pkts_mask, &ipv4_pkts_mask, &ipv6_pkts_mask); } if (nb_rx) { if (arp_pkts_mask) { proto_list[ARP_VAL]->func(pkts_burst, nb_rx, arp_pkts_mask, port); printf ("=================After ARP ==================\n"); } if (ipv4_pkts_mask) { printf ("=================Calling IPV4 L3 RX ==================\n"); printf("====nb_rx:%u, ipv4_pkts_mask: %lu\n\n", nb_rx, ipv4_pkts_mask); proto_list[IPv4_VAL]->func(pkts_burst, nb_rx, ipv4_pkts_mask, port); } if (ipv6_pkts_mask) { printf ("=================Calling IPV6 L3 RX ==================\n"); printf("====nb_rx:%u, ipv6_pkts_mask: %lu\n\n", nb_rx, ipv6_pkts_mask); proto_list[IPv6_VAL]->func(pkts_burst, nb_rx, ipv6_pkts_mask, port); } } } #if 0 switch (qid) { case 1: { #if 0 printf ("=====================ENTERED ARP CASE================\n"); while (cur->type != ETHER_TYPE_ARP && cur != NULL) { cur = cur->next; } if (cur != NULL) { //printf("L2 PROTO TEST-14=================================\n"); printf ("==============\nARPARPARPARP \n=======================\n"); cur->func(pkts_burst, nb_rx, pkts_mask, portid); } #endif proto_list[ARP_VAL]->func(pkts_burst, nb_rx, arp_pkts_mask, portid); break; } case 0: { #if 0 while (cur->type != ETHER_TYPE_IPv4 && cur != NULL) { cur = cur->next; } if (cur != NULL) { //printf("L2 PROTO TEST-15=================================\n"); //printf("==============\nPkts mask in while calling IPv4 %d \n=======================\n",ipv4_pkts_mask); cur->func(pkts_burst, nb_rx, ipv4_pkts_mask, portid); } break; #endif // printf("=========Inside switch==============\n"); proto_list[IPv4_VAL]->func(pkts_burst, nb_rx, ipv4_pkts_mask, portid); break; } /* case 2: { while(cur->type != ETHER_TYPE_IPv6 && cur != NULL) { cur = cur->next; } if(cur != NULL) { cur->func(pkts_burst, nb_rx, ipv6_pkts_mask, portid); } break; } */ default: { rte_exit(EXIT_FAILURE, "Ethertype not found \n"); break; } } #endif /* * L2 Stack Init for future void l2_stack_init(void) { } */