Merge "tools: Support multiple version of DPDK build"
[samplevnf.git] / common / VIL / l2l3_stack / l2_proto.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 /*
18  *      Filename - l2_proto.c
19  *      L2 Protocol Handler
20  */
21
22 #include "l2_proto.h"
23
24 static struct proto_packet_type *proto_list[3];
25 /*
26  *      Function to register the rx functions for different ethertypes. This is maintained in a list.
27  */
28 void
29 list_add_type(uint16_t type,
30                                 void (*func) (struct rte_mbuf **, uint16_t, uint64_t,
31                                         l2_phy_interface_t *))
32 {
33         if (type == ETHER_TYPE_IPv4) {
34                 proto_list[IPv4_VAL] =
35                                 rte_malloc(NULL, sizeof(struct proto_packet_type),
36                                                  RTE_CACHE_LINE_SIZE);
37                 proto_list[IPv4_VAL]->type = type;
38                 proto_list[IPv4_VAL]->func = func;
39         }
40
41         else if (type == ETHER_TYPE_ARP) {
42                 proto_list[ARP_VAL] =
43                                 rte_malloc(NULL, sizeof(struct proto_packet_type),
44                                                  RTE_CACHE_LINE_SIZE);
45                 proto_list[ARP_VAL]->type = type;
46                 proto_list[ARP_VAL]->func = func;
47         } else if (type == ETHER_TYPE_IPv6) {
48                 proto_list[IPv6_VAL] =
49                                 rte_malloc(NULL, sizeof(struct proto_packet_type),
50                                                  RTE_CACHE_LINE_SIZE);
51                 proto_list[IPv6_VAL]->type = type;
52                 proto_list[IPv6_VAL]->func = func;
53         }
54
55 }
56
57 /*
58  *      Check the mac address to see whether it is destined to this host or not.
59  *      Call relevant functions registered by other modules when the ethertype matches,
60  *      if it is destined to this host. Drop the packet otherwise.
61  */
62
63 void
64 l2_check_mac(struct rte_mbuf *m[IFM_BURST_SIZE], l2_phy_interface_t *port,
65                          uint8_t i, uint64_t *pkts_mask, uint64_t *arp_pkts_mask,
66                          uint64_t *ipv4_pkts_mask, uint64_t *ipv6_pkts_mask)
67 {
68         struct ether_hdr *eth=NULL;
69         uint16_t same_mac=0;
70         uint16_t ethtype = 0;
71
72         if (m[i] != NULL) {
73                 eth = rte_pktmbuf_mtod(m[i], struct ether_hdr *);
74                 if(eth)
75                 ethtype = rte_be_to_cpu_16(eth->ether_type);
76                 if (eth == NULL) {
77                         /*Destination MAC address inside the packet */
78                         printf("l2_check_mac: Ethernet Dest Addr NULL !!!\n");
79                         return;
80                 }
81                 ethtype = rte_be_to_cpu_16(eth->ether_type);
82 #if L2_PROTO_DBG
83                 printf("%s => mbuf pkt dest mac addr: %x:%x:%x:%x:%x:%x\n",
84                                          __FUNCTION__, eth->d_addr.addr_bytes[0],
85                                          eth->d_addr.addr_bytes[1], eth->d_addr.addr_bytes[2],
86                                          eth->d_addr.addr_bytes[3], eth->d_addr.addr_bytes[4],
87                                          eth->d_addr.addr_bytes[5]);
88                 printf("%s => port mac addr: %x:%x:%x:%x:%x:%x\n", __FUNCTION__,
89                                          port->macaddr[0], port->macaddr[1], port->macaddr[2],
90                                          port->macaddr[3], port->macaddr[4], port->macaddr[5]);
91
92 #endif
93                 /*     Compare the mac addresses       */
94                 same_mac =
95                                 (is_same_ether_addr
96                                  (&eth->d_addr, (struct ether_addr *)port->macaddr)
97                                  ||
98                                  ((is_broadcast_ether_addr
99                                          ((struct ether_addr *)&eth->d_addr)
100                                          && (ethtype == ETHER_TYPE_ARP)))
101                                  || (ethtype == ETHER_TYPE_IPv6
102                          && eth->d_addr.addr_bytes[0] == 0x33
103                          && eth->d_addr.addr_bytes[1] == 0x33));
104
105                 if (!same_mac) {
106                         uint64_t temp_mask = 1LLU << i;
107                         *pkts_mask ^= temp_mask;
108                         rte_pktmbuf_free(m[i]);
109                         m[i] = NULL;
110                 } else if ((ethtype == ETHER_TYPE_IPv4) && same_mac) {
111                         uint64_t temp_mask = 1LLU << i;
112                         *ipv4_pkts_mask ^= temp_mask;
113                 } else if ((ethtype == ETHER_TYPE_ARP) && same_mac) {
114                         uint64_t temp_mask = 1LLU << i;
115                         *arp_pkts_mask ^= temp_mask;
116                 } else if ((ethtype == ETHER_TYPE_IPv6) && same_mac) {
117                         uint64_t temp_mask = 1LLU << i;
118                         *ipv6_pkts_mask ^= temp_mask;
119                 }
120         }
121         printf("\n%s: arp_pkts_mask = %" PRIu64 ", ipv4_pkts_mask = %" PRIu64
122                                  ", ipv6_pkts_mask =%" PRIu64 ", pkt-type = %x, sam_mac = %d\n",
123                                  __FUNCTION__, *arp_pkts_mask, *ipv4_pkts_mask, *ipv6_pkts_mask,
124                                  ethtype, same_mac);
125 }
126
127 void
128 protocol_handler_recv(struct rte_mbuf **pkts_burst, uint16_t nb_rx,
129                                         l2_phy_interface_t *port)
130 {
131         uint8_t i;
132         uint64_t pkts_mask = 0; //RTE_LEN2MASK(nb_rx, uint64_t);
133         uint64_t arp_pkts_mask = 0;     //RTE_LEN2MASK(nb_rx, uint64_t);
134         uint64_t ipv4_pkts_mask = 0;    //RTE_LEN2MASK(nb_rx, uint64_t);
135         uint64_t ipv6_pkts_mask = 0;    //RTE_LEN2MASK(nb_rx, uint64_t);
136
137         /*Check the mac address of every single packet and unset the bits in the packet mask
138          *for those packets which are not destined to this host
139          */
140         for (i = 0; i < nb_rx; i++) {
141                 l2_check_mac(pkts_burst, port, i, &pkts_mask, &arp_pkts_mask,
142                                          &ipv4_pkts_mask, &ipv6_pkts_mask);
143         }
144         if (nb_rx) {
145                 if (arp_pkts_mask) {
146                         proto_list[ARP_VAL]->func(pkts_burst, nb_rx,
147                                                         arp_pkts_mask, port);
148                         printf
149                                         ("=================After ARP ==================\n");
150                 }
151                 if (ipv4_pkts_mask) {
152                         printf
153                                         ("=================Calling IPV4 L3 RX ==================\n");
154                         printf("====nb_rx:%u, ipv4_pkts_mask: %lu\n\n", nb_rx,
155                                                  ipv4_pkts_mask);
156                         proto_list[IPv4_VAL]->func(pkts_burst, nb_rx,
157                                                          ipv4_pkts_mask, port);
158                 }
159                 if (ipv6_pkts_mask) {
160                         printf
161                                         ("=================Calling IPV6 L3 RX ==================\n");
162                         printf("====nb_rx:%u, ipv6_pkts_mask: %lu\n\n", nb_rx,
163                                                  ipv6_pkts_mask);
164                         proto_list[IPv6_VAL]->func(pkts_burst, nb_rx,
165                                                          ipv6_pkts_mask, port);
166                 }
167         }
168 }
169
170 #if 0
171 switch (qid) {
172 case 1:
173         {
174 #if 0
175                 printf
176                                 ("=====================ENTERED ARP CASE================\n");
177                 while (cur->type != ETHER_TYPE_ARP && cur != NULL) {
178                         cur = cur->next;
179                 }
180                 if (cur != NULL) {
181                         //printf("L2 PROTO TEST-14=================================\n");
182                         printf
183                                         ("==============\nARPARPARPARP  \n=======================\n");
184                         cur->func(pkts_burst, nb_rx, pkts_mask, portid);
185                 }
186 #endif
187                 proto_list[ARP_VAL]->func(pkts_burst, nb_rx, arp_pkts_mask,
188                                                 portid);
189                 break;
190         }
191 case 0:
192         {
193 #if 0
194                 while (cur->type != ETHER_TYPE_IPv4 && cur != NULL) {
195                         cur = cur->next;
196                 }
197                 if (cur != NULL) {
198                         //printf("L2 PROTO TEST-15=================================\n");
199                         //printf("==============\nPkts mask in while calling IPv4 %d \n=======================\n",ipv4_pkts_mask);
200                         cur->func(pkts_burst, nb_rx, ipv4_pkts_mask, portid);
201                 }
202                 break;
203 #endif
204                 //      printf("=========Inside switch==============\n");
205                 proto_list[IPv4_VAL]->func(pkts_burst, nb_rx, ipv4_pkts_mask,
206                                                  portid);
207                 break;
208         }
209         /*     case 2:
210                  {
211                  while(cur->type != ETHER_TYPE_IPv6  && cur != NULL)
212                  {
213                  cur = cur->next;
214                  }
215                  if(cur != NULL)
216                  {
217                  cur->func(pkts_burst, nb_rx, ipv6_pkts_mask, portid);
218                  }
219                  break;
220                  } */
221 default:
222         {
223                 rte_exit(EXIT_FAILURE, "Ethertype not found \n");
224                 break;
225         }
226 }
227 #endif
228
229 /*
230  *      L2 Stack Init for future
231
232
233         void
234 l2_stack_init(void)
235 {
236
237 }
238
239 */