Line data Source code
1 : /*
2 : * vr_interface.c -- router interface management
3 : *
4 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
5 : * Copyright Contributors to the OpenSDN project
6 : */
7 : #include <vr_os.h>
8 : #include <vr_types.h>
9 : #include <vr_packet.h>
10 : #include <vr_interface.h>
11 : #include "vr_message.h"
12 : #include "vr_sandesh.h"
13 : #include "vr_mirror.h"
14 : #include "vr_htable.h"
15 : #include "vr_datapath.h"
16 : #include "vr_bridge.h"
17 : #include "vr_btable.h"
18 : #include "vr_route.h"
19 : #include "vr_ip_mtrie.h"
20 : #include "vr_offloads_dp.h"
21 : #include "vr_hash.h"
22 :
23 : unsigned int vr_interfaces = VR_MAX_INTERFACES;
24 :
25 : volatile bool agent_alive = false;
26 :
27 : static struct vr_host_interface_ops *hif_ops;
28 :
29 : static int vm_srx(struct vr_interface *, struct vr_packet *, unsigned short);
30 : static int vm_rx(struct vr_interface *, struct vr_packet *, unsigned short);
31 : static int eth_rx(struct vr_interface *, struct vr_packet *, unsigned short);
32 : static mac_response_t vm_mac_request(struct vr_interface *, struct vr_packet *,
33 : struct vr_forwarding_md *, unsigned char *);
34 : static void vif_fat_flow_free(uint8_t **);
35 : static int vif_fat_flow_add(struct vr_interface *, vr_interface_req *);
36 : static uint8_t vif_fat_flow_port_get(struct vr_interface *, uint8_t,
37 : uint16_t);
38 : static void __vif_fat_flow_free_all_rule_data_list(vr_fat_flow_prefix_rule_data_t *head);
39 :
40 : int vr_gro_vif_add(struct vrouter *, unsigned int, char *, unsigned short);
41 : struct vr_interface_stats *vif_get_stats(struct vr_interface *, unsigned short);
42 : struct vr_interface *__vrouter_get_interface_os(struct vrouter *, unsigned int);
43 :
44 : extern struct vr_host_interface_ops *vr_host_interface_init(void);
45 : extern void vr_host_interface_exit(void);
46 : extern void vr_host_vif_init(struct vrouter *);
47 : extern struct vr_interface *vif_bridge_get_sub_interface(vr_htable_t,
48 : unsigned short, unsigned char *);
49 : extern int vif_bridge_get_index(struct vr_interface *, struct
50 : vr_interface *, uint8_t *);
51 : extern int vif_bridge_init(struct vr_interface *);
52 : extern void vif_bridge_deinit(struct vr_interface *);
53 : extern int vif_bridge_delete(struct vr_interface *, struct vr_interface
54 : *, uint8_t *);
55 : extern int vif_bridge_add(struct vr_interface *, struct vr_interface *,
56 : uint8_t *);
57 : extern void vhost_remove_xconnect(void);
58 : extern void vr_drop_stats_get_vif_stats(vr_drop_stats_req *, struct vr_interface *);
59 :
60 : static vr_fat_flow_prefix_rule_data_t dummy_rule = {0};
61 : static int dummy_plen = 255;
62 :
63 : #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
64 :
65 : static inline uint64_t
66 0 : vr_htonll (uint64_t n)
67 : {
68 0 : uint64_t t = 1;
69 : uint8_t *p, out[8];
70 :
71 0 : if (*((uint8_t *) &t) == 1) {
72 0 : p = (uint8_t *) &n;
73 0 : out[0] = *(p + 7);
74 0 : out[1] = *(p + 6);
75 0 : out[2] = *(p + 5);
76 0 : out[3] = *(p + 4);
77 0 : out[4] = *(p + 3);
78 0 : out[5] = *(p + 2);
79 0 : out[6] = *(p + 1);
80 0 : out[7] = *(p + 0);
81 0 : return (*((uint64_t *) out));
82 : }
83 0 : return n;
84 : }
85 :
86 : static inline void
87 0 : fat_flow_ipv6_plen_to_mask (uint16_t plen, uint64_t *high_mask, uint64_t *low_mask)
88 : {
89 0 : if (plen > 64) {
90 0 : *high_mask = 0xFFFFFFFFFFFFFFFF;
91 0 : *low_mask = vr_htonll((0xFFFFFFFFFFFFFFFF << (128 - plen)));
92 : } else {
93 0 : *low_mask = 0;
94 0 : *high_mask = vr_htonll((0xFFFFFFFFFFFFFFFF << (64 - plen)));
95 : }
96 0 : }
97 :
98 : struct vr_interface_stats *
99 4385 : vif_get_stats(struct vr_interface *vif, unsigned short cpu)
100 : {
101 4385 : return &vif->vif_stats[cpu & VR_CPU_MASK];
102 : }
103 :
104 : static int
105 0 : vif_discard_tx(struct vr_interface *vif, struct vr_packet *pkt,
106 : struct vr_forwarding_md *fmd)
107 : {
108 0 : PKT_LOG(VP_DROP_INTERFACE_TX_DISCARD, pkt, 0, VR_INTERFACE_C, __LINE__);
109 0 : vr_pfree(pkt, VP_DROP_INTERFACE_TX_DISCARD);
110 0 : return 0;
111 : }
112 :
113 : static int
114 0 : vif_discard_rx(struct vr_interface *vif, struct vr_packet *pkt,
115 : unsigned short vlan_id __attribute__unused__)
116 : {
117 0 : PKT_LOG(VP_DROP_INTERFACE_RX_DISCARD, pkt, 0, VR_INTERFACE_C, __LINE__);
118 0 : vr_pfree(pkt, VP_DROP_INTERFACE_RX_DISCARD);
119 0 : return 0;
120 : }
121 :
122 : void
123 0 : vif_drop_pkt(struct vr_interface *vif, struct vr_packet *pkt, bool input)
124 : {
125 0 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
126 :
127 0 : if (input)
128 0 : stats->vis_ierrors++;
129 : else
130 0 : stats->vis_oerrors++;
131 :
132 0 : PKT_LOG(VP_DROP_INTERFACE_DROP, pkt, 0, VR_INTERFACE_C, __LINE__);
133 0 : vr_pfree(pkt, VP_DROP_INTERFACE_DROP);
134 0 : return;
135 : }
136 :
137 : /*
138 : * in the rewrite case, we will assume the positive case of caller
139 : * passing us valid rewrite ptr and len and will not check for those
140 : */
141 : static int
142 94 : vif_cmn_rewrite(struct vr_interface *vif, struct vr_packet **pkt,
143 : struct vr_forwarding_md *fmd, unsigned char *rewrite,
144 : unsigned short len)
145 : {
146 : unsigned char *head;
147 : struct vr_packet *expanded_pkt;
148 :
149 94 : if (!len)
150 0 : return 0;
151 :
152 94 : if (pkt_head_space(*pkt) < len) {
153 0 : expanded_pkt = vr_pexpand_head(*pkt, len - pkt_head_space(*pkt));
154 0 : if (!expanded_pkt)
155 0 : return -ENOMEM;
156 0 : *pkt = expanded_pkt;
157 : }
158 :
159 94 : head = pkt_push(*pkt, len);
160 94 : if (!head)
161 0 : return -ENOMEM;
162 :
163 94 : memcpy(head, rewrite, len);
164 94 : return len;
165 : }
166 :
167 : static int
168 0 : vr_interface_service_enable(struct vr_interface *vif)
169 : {
170 : int i;
171 :
172 : /*
173 : * handle the case of existing vrf assign table, which
174 : * was not freed because the table was not empty. also,
175 : * note that for existing vrf table, we do not reset the
176 : * entries and the table users count, as per requirements
177 : * from agent
178 : */
179 0 : if (!vif->vif_vrf_table) {
180 0 : vif->vif_vrf_table = vr_malloc(sizeof(struct vr_vrf_assign) *
181 : VIF_VRF_TABLE_ENTRIES, VR_INTERFACE_VRF_TABLE_OBJECT);
182 0 : if (!vif->vif_vrf_table)
183 0 : return -ENOMEM;
184 :
185 0 : for (i = 0; i < VIF_VRF_TABLE_ENTRIES; i++) {
186 0 : vif->vif_vrf_table[i].va_vrf = -1;
187 0 : vif->vif_vrf_table[i].va_nh_id = 0;
188 : }
189 :
190 : /* for the new table, there are no users */
191 0 : vif->vif_vrf_table_users = 0;
192 : }
193 :
194 0 : vif->vif_rx = vm_srx;
195 :
196 0 : return 0;
197 : }
198 :
199 :
200 : static void
201 0 : vr_interface_service_disable(struct vr_interface *vif)
202 : {
203 :
204 0 : if (vif_is_virtual(vif))
205 0 : vif->vif_rx = vm_rx;
206 : else
207 0 : vif->vif_rx = eth_rx;
208 :
209 : /*
210 : * once everybody sees the change, we are free to do whatever
211 : * we want with the vrf assign table
212 : */
213 0 : if (!vr_not_ready)
214 0 : vr_delay_op();
215 :
216 : /*
217 : * it is possible that when this function is called from
218 : * interface delete, the table users are +ve, and hence
219 : * the memory will not be freed here. our saving grace
220 : * is vif_free (called from last put operation), which
221 : * takes care of freeing the memory
222 : */
223 0 : if (vif->vif_vrf_table && !vif->vif_vrf_table_users) {
224 0 : vr_free(vif->vif_vrf_table, VR_INTERFACE_VRF_TABLE_OBJECT);
225 0 : vif->vif_vrf_table = NULL;
226 : }
227 :
228 0 : return;
229 : }
230 :
231 : /*
232 : * xconnect mode
233 : *
234 : * xconnect mode, as of now, is relevant only for physical (ethX) and vhost
235 : * interfaces. the purpose of xconnect mode is to make sure that the host
236 : * management interface does not lose connectivity to network when agent is
237 : * either not started or not alive.
238 : *
239 : * the xconnect mode works differently in different devices. since for ethernet
240 : * interfaces, we would still like to process all packets destined to VMs,
241 : * packets will have to be processed by the vrouter stack. however, for vhost
242 : * interfaces, we just need the packets to be pushed to ethernet interface,
243 : * and hence the packets are switched to the corresponding physical interface
244 : */
245 : void
246 98 : vif_set_xconnect(struct vr_interface *vif)
247 : {
248 98 : if (!vif)
249 0 : return;
250 :
251 98 : vif->vif_flags |= VIF_FLAG_XCONNECT;
252 98 : return;
253 : }
254 :
255 : void
256 86 : vif_remove_xconnect(struct vr_interface *vif)
257 : {
258 86 : if (!vif)
259 0 : return;
260 :
261 86 : vif->vif_flags &= ~VIF_FLAG_XCONNECT;
262 86 : return;
263 : }
264 :
265 2 : static void vr_pkt_dump(struct vr_packet *pkt)
266 : {
267 2 : pkt_dump(pkt);
268 2 : if (hif_ops->hif_pkt_dump) {
269 0 : hif_ops->hif_pkt_dump(pkt);
270 : }
271 2 : }
272 :
273 : static struct vr_interface *
274 3 : vr_get_arp_xconnect_interface_mh (struct vr_interface *vif, struct vr_packet *pkt)
275 : {
276 3 : struct vr_arp *arp = NULL;
277 3 : struct vrouter *router = vrouter_get(0);
278 : unsigned int addr, mask, i;
279 : unsigned char *mac;
280 :
281 3 : if(!is_vrouter_multihomed(router)) {
282 : /* Not multi-homed */
283 0 : return NULL;
284 : }
285 :
286 3 : arp = (struct vr_arp *) pkt_data(pkt);
287 3 : if (vif_is_vhost(vif)) {
288 :
289 1 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
290 1 : if (vif->vif_bridge[i]) {
291 1 : if (hif_ops->hif_get_host_mac_addr) {
292 1 : hif_ops->hif_get_host_mac_addr(vif->vif_bridge[i], &mac);
293 :
294 1 : if (!memcmp(arp->arp_sha, mac, 6)) {
295 0 : if(vif->vif_bridge[i]) {
296 0 : return vif->vif_bridge[i];
297 : } else {
298 0 : vr_printf("%s: vif->vif_bridge[%d] is NULL\n",
299 : __func__, i);
300 0 : return NULL;
301 : }
302 : }
303 : }
304 :
305 : /* select the interface based on dst ip being queried */
306 1 : if (hif_ops->hif_get_host_ip_mask) {
307 1 : hif_ops->hif_get_host_ip_mask(vif->vif_bridge[i], &addr, &mask);
308 :
309 1 : if ((arp->arp_dpa & mask) == (addr & mask)) {
310 1 : if(vif->vif_bridge[i]) {
311 1 : return vif->vif_bridge[i];
312 : } else {
313 0 : vr_printf("%s: vif->vif_bridge[%d] is NULL\n",
314 : __func__, i);
315 0 : return NULL;
316 : }
317 : }
318 : }
319 : }
320 : }
321 :
322 0 : vr_printf("Unable to select int for arp pkt %p\n", pkt);
323 0 : return NULL;
324 2 : } else if (vif_is_fabric(vif)) {
325 : /* send it to host using same fabric interface */
326 2 : vr_pkt_dump(pkt);
327 2 : return vif;
328 : }
329 0 : return NULL;
330 : }
331 :
332 : static struct vr_interface *
333 0 : vr_get_ip_xconnect_interface_mh (struct vr_interface *vif, struct vr_packet *pkt)
334 : {
335 : /* calculate 5 tuple hash of the ip pkt and send it to one of
336 : the interfaces */
337 0 : uint32_t hash, i, count = 0;
338 0 : struct vrouter *router = vrouter_get(0);
339 :
340 0 : if (vif_is_vhost(vif)) {
341 0 : hash = vr_get_pkt_hash(pkt);
342 0 : hash = hash % router->vr_num_phy_interfaces;
343 0 : if(hash < VR_MAX_PHY_INF) {
344 0 : for(i = 0; i < VR_MAX_PHY_INF; i++) {
345 0 : if((router->vr_l3mh_intf_bitpos >> i) & 0x1) {
346 0 : if(count == hash) {
347 0 : return __vrouter_get_interface(router, i);
348 : }
349 0 : count++;
350 : }
351 : }
352 0 : vr_printf("%s L3MH: Interface bitposition is invalid %d \n", __func__,
353 0 : router->vr_l3mh_intf_bitpos);
354 : } else {
355 0 : vr_printf("%s: Invalid hash value: %d\n", __func__, hash);
356 0 : return NULL;
357 : }
358 : }
359 0 : return NULL;
360 : }
361 :
362 : static int
363 2 : vr_deliver_os_interface(struct vr_interface *vif, struct vr_packet *pkt,
364 : struct vr_forwarding_md *fmd)
365 : {
366 2 : return hif_ops->hif_rx_pass ? hif_ops->hif_rx_pass(vif, pkt) : 0;
367 : }
368 : /*
369 : * NOTE: This API can return RX_HANDLER_PASS which means the same pkt
370 : * needs to be passed up the linux kernel stack (pkt->vp_rx_pass = 1).
371 : * Care should be taken in cloned pkt cases, such that this pkt
372 : * which can be marked with rx_pass is sent to the rx handler
373 : * instead of the cloned pkt (which won't have the rx_pass flag
374 : * set). As a rule of thumb, if this API is called with a pkt,
375 : * the same pkt should always be sent back to the rx_handler.
376 : */
377 :
378 : int
379 18 : vif_xconnect(struct vr_interface *vif, struct vr_packet *pkt,
380 : struct vr_forwarding_md *fmd)
381 : {
382 : struct vr_interface *bridge;
383 18 : struct vrouter *router = vrouter_get(0);
384 : int ret;
385 :
386 18 : if (!vif)
387 0 : goto free_pkt;
388 :
389 18 : if (is_vrouter_multihomed(router)) {
390 6 : if (pkt->vp_type == VP_TYPE_ARP) {
391 3 : bridge = vr_get_arp_xconnect_interface_mh(vif, pkt);
392 3 : if (bridge && (bridge == vif)) {
393 : /* pkts received from fabric, xconnect to same interface */
394 2 : vr_preset(pkt);
395 2 : ret = vr_deliver_os_interface(bridge, pkt, fmd);
396 2 : if(ret)
397 0 : return ret;
398 2 : bridge = vif->vif_bridge[0];
399 : }
400 3 : if (!bridge) {
401 0 : bridge = vif->vif_bridge[0];
402 : }
403 3 : } else if ((pkt->vp_type == VP_TYPE_IP) ||
404 3 : (pkt->vp_type == VP_TYPE_IP6)) {
405 0 : bridge = vr_get_ip_xconnect_interface_mh(vif, pkt);
406 0 : if (!bridge) {
407 0 : bridge = vif->vif_bridge[0];
408 : }
409 : } else {
410 : /* other pkt type, send via phy_int_1 (for now) */
411 3 : bridge = vif->vif_bridge[0];
412 : }
413 : } else {
414 12 : bridge = vif->vif_bridge[0];
415 : }
416 :
417 18 : if (bridge) {
418 18 : vr_preset(pkt);
419 18 : return bridge->vif_tx(bridge, pkt, fmd);
420 : }
421 :
422 0 : free_pkt:
423 0 : if (vif)
424 0 : vif_drop_pkt(vif, pkt, 1);
425 0 : return 0;
426 : }
427 :
428 : static inline void
429 293 : vif_mirror(struct vr_interface *vif, struct vr_packet *pkt,
430 : struct vr_forwarding_md *fmd, unsigned int txrx_mirror)
431 : {
432 : unsigned int mirror_type;
433 : struct vr_forwarding_md mfmd;
434 : uint16_t vlan_id;
435 :
436 293 : if (!txrx_mirror)
437 293 : return;
438 :
439 0 : if (txrx_mirror & VIF_FLAG_MIRROR_TX)
440 0 : mirror_type = MIRROR_TYPE_PORT_TX;
441 : else
442 0 : mirror_type = MIRROR_TYPE_PORT_RX;
443 :
444 0 : if (!fmd) {
445 0 : vr_init_forwarding_md(&mfmd);
446 : } else {
447 0 : mfmd = *fmd;
448 : }
449 :
450 0 : mfmd.fmd_dvrf = vif->vif_vrf;
451 0 : vr_fmd_put_mirror_if_id(&mfmd, vif->vif_idx);
452 :
453 0 : if (pkt->vp_type == VP_TYPE_NULL)
454 0 : vr_pkt_type(pkt, 0, &mfmd);
455 :
456 0 : vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &mfmd, mirror_type);
457 :
458 0 : vlan_id = vr_fmd_get_mirror_vlan(&mfmd);
459 0 : if (vlan_id != FMD_MIRROR_INVALID_DATA)
460 0 : vr_fmd_put_mirror_vlan(fmd, vlan_id);
461 :
462 0 : return;
463 : }
464 :
465 : /* agent driver */
466 : static int
467 0 : agent_set_rewrite(struct vr_interface *vif, struct vr_packet **pkt,
468 : struct vr_forwarding_md *fmd, unsigned char *rewrite,
469 : unsigned short len)
470 : {
471 : unsigned char *head;
472 : unsigned int hdr_len;
473 : struct agent_hdr *hdr;
474 : uint8_t bfd_state;
475 : struct vr_packet *expanded_pkt;
476 :
477 0 : vr_preset(*pkt);
478 :
479 0 : hdr_len = sizeof(struct agent_hdr) + len;
480 0 : if (pkt_head_space(*pkt) < hdr_len) {
481 0 : expanded_pkt = vr_pexpand_head(*pkt, hdr_len - pkt_head_space(*pkt));
482 0 : if (!expanded_pkt)
483 0 : return -ENOMEM;
484 0 : *pkt = expanded_pkt;
485 : }
486 :
487 0 : head = pkt_push(*pkt, hdr_len);
488 0 : if (!head)
489 0 : return -ENOMEM;
490 :
491 : /* copy the rewrite first */
492 0 : memcpy(head, rewrite, len);
493 :
494 0 : hdr = (struct agent_hdr *)(head + len);
495 0 : hdr->hdr_ifindex = htons((*pkt)->vp_if->vif_idx);
496 0 : hdr->hdr_vrf = htons(fmd->fmd_dvrf);
497 0 : if (vr_pkt_is_bfd(*pkt, &bfd_state) == true) {
498 0 : hdr->hdr_cmd = htons(AGENT_TRAP_BFD);
499 : // set the BFD state info in cmd_param
500 0 : hdr->hdr_cmd_param = htonl(bfd_state);
501 : } else {
502 : /* this needs some thought */
503 0 : hdr->hdr_cmd = htons(AGENT_TRAP_NEXTHOP);
504 0 : hdr->hdr_cmd_param = 0;
505 : }
506 :
507 0 : return len;
508 : }
509 :
510 : static int
511 1 : agent_rx(struct vr_interface *vif, struct vr_packet *pkt,
512 : unsigned short vlan_id __attribute__unused__)
513 : {
514 : unsigned short cmd;
515 :
516 : struct agent_hdr *hdr;
517 : struct vr_forwarding_md fmd;
518 : struct vr_interface *agent_vif;
519 1 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
520 :
521 1 : stats->vis_ibytes += pkt_len(pkt);
522 1 : stats->vis_ipackets++;
523 :
524 1 : hdr = (struct agent_hdr *)pkt_pull(pkt, sizeof(struct vr_eth));
525 1 : if (!hdr || !pkt_pull(pkt, sizeof(*hdr))) {
526 0 : stats->vis_ierrors++;
527 0 : PKT_LOG(VP_DROP_PULL, pkt, 0, VR_INTERFACE_C, __LINE__);
528 0 : vr_pfree(pkt, VP_DROP_PULL);
529 0 : return 0;
530 : }
531 :
532 : /*
533 : * Update the original (OS visible) packet to point to the
534 : * l2 header of the injected packet
535 : */
536 1 : vr_pset_data(pkt, pkt->vp_data);
537 :
538 1 : cmd = ntohs(hdr->hdr_cmd);
539 :
540 1 : switch (cmd) {
541 1 : case AGENT_CMD_ROUTE:
542 : /*
543 : * XXX
544 : * Packet with command "route" from agent may
545 : * result in flow setup, this breaks the
546 : * assumption that all packets for a flow will
547 : * reach same CPU. Need a better way to handle this
548 : */
549 1 : agent_vif = __vrouter_get_interface(vrouter_get(0),
550 1 : ntohs(hdr->hdr_ifindex));
551 : /*
552 : * Don't set the pkt input vif to fabric as it leads to
553 : * wrong checks being made later in the code where
554 : * it thinks that the pkt really came in on a
555 : * fabric interface. In such cases, set the pkt input
556 : * vif to pkt0 vif
557 : */
558 1 : if ((!agent_vif) || (vif_is_fabric(agent_vif))) {
559 1 : agent_vif = vif;
560 : }
561 1 : pkt->vp_if = agent_vif;
562 :
563 1 : if (ntohl(hdr->hdr_cmd_param) == CMD_PARAM_PACKET_CTRL) {
564 0 : if (ntohl(hdr->hdr_cmd_param_1) == CMD_PARAM_1_DIAG) {
565 0 : pkt->vp_flags |= VP_FLAG_DIAG;
566 : }
567 : }
568 :
569 1 : vr_init_forwarding_md(&fmd);
570 1 : vr_virtual_input(ntohs(hdr->hdr_vrf), agent_vif, pkt,
571 : &fmd, VLAN_ID_INVALID);
572 :
573 1 : break;
574 :
575 0 : case AGENT_CMD_SWITCH:
576 0 : vif = __vrouter_get_interface(vrouter_get(0), ntohs(hdr->hdr_ifindex));
577 0 : if (!vif) {
578 0 : stats->vis_ierrors++;
579 0 : PKT_LOG(VP_DROP_INVALID_IF, pkt, 0, VR_INTERFACE_C, __LINE__);
580 0 : vr_pfree(pkt, VP_DROP_INVALID_IF);
581 0 : return 0;
582 : }
583 :
584 0 : vr_init_forwarding_md(&fmd);
585 0 : fmd.fmd_dvrf = ntohs(hdr->hdr_vrf);
586 :
587 0 : pkt->vp_type = VP_TYPE_AGENT;
588 0 : pkt_set_network_header(pkt, pkt->vp_data + sizeof(struct vr_eth));
589 0 : pkt_set_inner_network_header(pkt,
590 0 : pkt->vp_data + sizeof(struct vr_eth));
591 0 : return vif->vif_tx(vif, pkt, &fmd);
592 :
593 : break;
594 :
595 0 : default:
596 0 : PKT_LOG(VP_DROP_INVALID_PACKET, pkt, 0, VR_INTERFACE_C, __LINE__);
597 0 : vr_pfree(pkt, VP_DROP_INVALID_PACKET);
598 0 : break;
599 : }
600 :
601 1 : return 0;
602 : }
603 :
604 : static int
605 11 : agent_tx(struct vr_interface *vif, struct vr_packet *pkt,
606 : struct vr_forwarding_md *fmd)
607 : {
608 : int ret;
609 11 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
610 :
611 11 : stats->vis_obytes += pkt_len(pkt);
612 11 : stats->vis_opackets++;
613 :
614 11 : if (vif->vif_flags & VIF_FLAG_MOCK_DEVICE) {
615 11 : PKT_LOG(VP_DROP_INTERFACE_DROP, pkt, 0, VR_INTERFACE_C, __LINE__);
616 11 : vr_pfree(pkt, VP_DROP_INTERFACE_DROP);
617 11 : return 0;
618 : }
619 :
620 0 : ret = hif_ops->hif_tx(vif, pkt);
621 0 : if (ret != 0) {
622 0 : ret = 0;
623 0 : stats->vis_oerrors++;
624 : }
625 :
626 0 : return ret;
627 : }
628 :
629 : /*
630 : * Return true if the packet may be truncated.
631 : */
632 : static int
633 0 : agent_trap_may_truncate(int trap_reason)
634 : {
635 0 : switch (trap_reason) {
636 0 : case AGENT_TRAP_NEXTHOP:
637 : case AGENT_TRAP_RESOLVE:
638 : case AGENT_TRAP_FLOW_MISS:
639 : case AGENT_TRAP_FLOW_ACTION_HOLD:
640 : case AGENT_TRAP_ECMP_RESOLVE:
641 : case AGENT_TRAP_HANDLE_DF:
642 : case AGENT_TRAP_ZERO_TTL:
643 : case AGENT_TRAP_MAC_LEARN:
644 : case AGENT_TRAP_MAC_MOVE:
645 0 : return 1;
646 :
647 0 : case AGENT_TRAP_ARP:
648 : case AGENT_TRAP_L2_PROTOCOLS:
649 : case AGENT_TRAP_L3_PROTOCOLS:
650 : case AGENT_TRAP_DIAG:
651 : default:
652 0 : return 0;
653 : }
654 : }
655 :
656 : static int
657 11 : agent_send(struct vr_interface *vif, struct vr_packet *pkt,
658 : void *ifspecific)
659 : {
660 11 : unsigned short encap = VIF_ENCAP_TYPE_ETHER;
661 : int len, head_space;
662 : struct vr_eth *eth;
663 :
664 : struct vr_forwarding_md fmd;
665 : struct agent_hdr *hdr;
666 : unsigned char *rewrite;
667 11 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
668 : struct vr_packet *pkt_c;
669 11 : struct agent_send_params *params =
670 : (struct agent_send_params *)ifspecific;
671 : struct vr_flow_trap_arg *fta;
672 : struct vr_df_trap_arg *dta;
673 11 : bool truncate = false;
674 :
675 :
676 11 : vr_preset(pkt);
677 :
678 11 : if (pkt_is_gso(pkt)) {
679 0 : truncate = true;
680 : }
681 :
682 11 : if ((params->trap_reason == AGENT_TRAP_HANDLE_DF) ||
683 11 : (params->trap_reason == AGENT_TRAP_ZERO_TTL)) {
684 0 : if (pkt_len(pkt) > VR_AGENT_MIN_PACKET_LEN)
685 0 : truncate = true;
686 : }
687 :
688 11 : if (hif_ops->hif_get_encap)
689 11 : encap = hif_ops->hif_get_encap(pkt->vp_if);
690 :
691 11 : head_space = AGENT_PKT_HEAD_SPACE;
692 11 : if (encap == VIF_ENCAP_TYPE_L3)
693 0 : head_space += VR_ETHER_HLEN;
694 :
695 11 : if (truncate || (pkt_head_space(pkt) < head_space)) {
696 0 : len = pkt_len(pkt);
697 :
698 0 : if (agent_trap_may_truncate(params->trap_reason)) {
699 0 : len = MINIMUM(len, VR_AGENT_MIN_PACKET_LEN);
700 : }
701 :
702 0 : pkt_c = pkt_copy(pkt, 0, len);
703 0 : if (pkt_c) {
704 0 : PKT_LOG(VP_DROP_DUPLICATED, pkt, 0, VR_INTERFACE_C, __LINE__);
705 0 : vr_pfree(pkt, VP_DROP_DUPLICATED);
706 0 : pkt = pkt_c;
707 : }
708 : }
709 :
710 11 : pkt->vp_type = VP_TYPE_AGENT;
711 :
712 11 : if (encap == VIF_ENCAP_TYPE_L3) {
713 0 : eth = (struct vr_eth *)(pkt_push(pkt, VR_ETHER_HLEN));
714 0 : if (!eth) {
715 0 : PKT_LOG(VP_DROP_PUSH, pkt, 0, VR_INTERFACE_C, __LINE__);
716 0 : goto drop;
717 : }
718 :
719 0 : memcpy(eth->eth_dmac, vif->vif_mac, VR_ETHER_ALEN);
720 0 : memcpy(eth->eth_smac, vif->vif_mac, VR_ETHER_ALEN);
721 0 : if (pkt->vp_type == VP_TYPE_IP6)
722 0 : eth->eth_proto = htons(VR_ETH_PROTO_IP6);
723 : else
724 0 : eth->eth_proto = htons(VR_ETH_PROTO_IP);
725 : }
726 :
727 11 : pkt_set_network_header(pkt, pkt->vp_data + sizeof(struct vr_eth));
728 11 : pkt_set_inner_network_header(pkt,
729 11 : pkt->vp_data + sizeof(struct vr_eth));
730 :
731 11 : hdr = (struct agent_hdr *)pkt_push(pkt, sizeof(struct agent_hdr));
732 11 : if (!hdr) {
733 0 : PKT_LOG(VP_DROP_PUSH, pkt, 0, VR_INTERFACE_C, __LINE__);
734 0 : goto drop;
735 : }
736 :
737 11 : hdr->hdr_ifindex = htons(pkt->vp_if->vif_idx);
738 11 : hdr->hdr_vrf = htons(params->trap_vrf);
739 11 : hdr->hdr_cmd = htons(params->trap_reason);
740 :
741 11 : switch (params->trap_reason) {
742 2 : case AGENT_TRAP_FLOW_MISS:
743 : case AGENT_TRAP_FLOW_ACTION_HOLD:
744 2 : if (params->trap_param) {
745 2 : fta = (struct vr_flow_trap_arg *)(params->trap_param);
746 2 : hdr->hdr_cmd_param = htonl(fta->vfta_index);
747 2 : hdr->hdr_cmd_param_1 = htonl(fta->vfta_nh_index);
748 2 : hdr->hdr_cmd_param_2 = htonl(fta->vfta_stats.flow_bytes);
749 2 : hdr->hdr_cmd_param_3 = htonl(fta->vfta_stats.flow_packets);
750 2 : hdr->hdr_cmd_param_4 = htonl((fta->vfta_stats.flow_bytes_oflow |
751 2 : (fta->vfta_stats.flow_packets_oflow << 16)));
752 2 : hdr->hdr_cmd_param_5 = fta->vfta_gen_id;
753 : }
754 2 : break;
755 :
756 7 : case AGENT_TRAP_ECMP_RESOLVE:
757 : case AGENT_TRAP_SOURCE_MISMATCH:
758 : case AGENT_TRAP_DIAG:
759 : case AGENT_TRAP_MAC_LEARN:
760 : case AGENT_TRAP_MAC_MOVE:
761 : case AGENT_TRAP_MAC_IP_LEARNING:
762 7 : if (params->trap_param)
763 0 : hdr->hdr_cmd_param = htonl(*(unsigned int *)(params->trap_param));
764 7 : break;
765 :
766 0 : case AGENT_TRAP_HANDLE_DF:
767 0 : dta = (struct vr_df_trap_arg *)(params->trap_param);
768 0 : hdr->hdr_cmd_param = htonl(dta->df_mtu);
769 0 : hdr->hdr_cmd_param_1 = htonl(dta->df_flow_index);
770 0 : break;
771 :
772 2 : default:
773 2 : hdr->hdr_cmd_param = 0;
774 2 : hdr->hdr_cmd_param_1 = 0;
775 2 : break;
776 : }
777 :
778 11 : rewrite = pkt_push(pkt, VR_ETHER_HLEN);
779 11 : if (!rewrite) {
780 0 : PKT_LOG(VP_DROP_PUSH, pkt, 0, VR_INTERFACE_C, __LINE__);
781 0 : goto drop;
782 : }
783 :
784 11 : memcpy(rewrite, vif->vif_rewrite, VR_ETHER_HLEN);
785 :
786 11 : vr_init_forwarding_md(&fmd);
787 11 : return vif->vif_tx(vif, pkt, &fmd);
788 :
789 0 : drop:
790 0 : stats->vis_oerrors++;
791 0 : vr_pfree(pkt, VP_DROP_PUSH);
792 0 : return 0;
793 : }
794 :
795 : static int
796 42 : agent_drv_del(struct vr_interface *vif)
797 : {
798 42 : hif_ops->hif_del_tap(vif);
799 :
800 42 : vif->vif_tx = vif_discard_tx;
801 42 : vif->vif_rx = vif_discard_rx;
802 :
803 42 : return hif_ops->hif_del(vif);
804 : }
805 :
806 : static int
807 42 : agent_drv_add(struct vr_interface *vif,
808 : vr_interface_req *vifr)
809 : {
810 : int ret;
811 :
812 42 : if (!vif->vif_mtu)
813 0 : vif->vif_mtu = 1514;
814 :
815 42 : vif->vif_set_rewrite = agent_set_rewrite;
816 :
817 : /**
818 : * At this moment, vif_tx() and vif_rx() are vif_discard_tx() and
819 : * vif_discard_rx(). Let them stay this way until we succesfully call
820 : * platform-dependent implementation of hif_add(). On some platfoms it may
821 : * set up resoruces needed by hif_tx(), which is called by agent_tx().
822 : */
823 42 : ret = hif_ops->hif_add(vif);
824 42 : if (ret) {
825 0 : return ret;
826 : }
827 :
828 42 : vif->vif_tx = agent_tx;
829 42 : vif->vif_rx = agent_rx;
830 42 : vif->vif_send = agent_send;
831 :
832 42 : ret = hif_ops->hif_add_tap(vif, vifr);
833 42 : if (ret)
834 0 : hif_ops->hif_del(vif);
835 :
836 42 : return ret;
837 : }
838 : /* end agent driver */
839 :
840 : /* vhost driver */
841 : static mac_response_t
842 2 : vhost_mac_request(struct vr_interface *vif, struct vr_packet *pkt,
843 : struct vr_forwarding_md *fmd, unsigned char *dmac)
844 : {
845 : struct vr_arp *sarp;
846 2 : mac_response_t mr = MR_XCONNECT;
847 :
848 : /*
849 : * Handle all the special cases here. Invoke vm_mac_request(), if
850 : * the decision to respond is based on standard condittions of
851 : * overloay
852 : */
853 2 : if (pkt->vp_type == VP_TYPE_ARP) {
854 :
855 : /* Grat ARP, cross connect */
856 1 : sarp = (struct vr_arp *)pkt_data(pkt);
857 1 : if (vr_grat_arp(sarp))
858 0 : return MR_XCONNECT;
859 :
860 1 : if (IS_LINK_LOCAL_IP(sarp->arp_dpa) ||
861 1 : (vif->vif_type == VIF_TYPE_GATEWAY)) {
862 0 : VR_MAC_COPY(dmac, vif->vif_mac);
863 0 : return MR_PROXY;
864 : }
865 :
866 1 : mr = vm_mac_request(vif, pkt, fmd, dmac);
867 1 : if ((mr != MR_XCONNECT) && (mr != MR_PROXY)) {
868 0 : vr_printf("Vrouter: Vhost arp request Mr %d Dst %x src %x"
869 : " converting to Xconnect\n", mr, sarp->arp_dpa,
870 : sarp->arp_spa);
871 :
872 0 : mr = MR_XCONNECT;
873 : }
874 1 : } else if (vr_is_ipv6_nd_packet(pkt)) {
875 1 : mr = vm_mac_request(vif, pkt, fmd, dmac);
876 1 : if ((mr != MR_XCONNECT) && (mr != MR_PROXY)) {
877 1 : mr = MR_XCONNECT;
878 : }
879 : } else {
880 : /* Handle V6 */
881 0 : if (vif->vif_type == VIF_TYPE_GATEWAY)
882 0 : mr = MR_DROP;
883 : }
884 :
885 2 : return mr;
886 : }
887 :
888 : static int
889 13 : vhost_rx(struct vr_interface *vif, struct vr_packet *pkt,
890 : unsigned short vlan_id __attribute__unused__)
891 : {
892 : struct vr_forwarding_md fmd;
893 13 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
894 :
895 13 : stats->vis_ibytes += pkt_len(pkt);
896 13 : stats->vis_ipackets++;
897 :
898 13 : vr_init_forwarding_md(&fmd);
899 13 : fmd.fmd_dvrf = vif->vif_vrf;
900 :
901 : /*
902 : * TODO: Xconnect mode: Ideally all the flow processing need to happen
903 : * even in this mode. If there is no existing flow available, then
904 : * it can be chosen to be cross connected. For the time being, all
905 : * are cross connected
906 : */
907 13 : if (vif_mode_xconnect(vif))
908 3 : return vif_xconnect(vif, pkt, &fmd);
909 :
910 10 : vif_mirror(vif, pkt, &fmd, vif->vif_flags & VIF_FLAG_MIRROR_RX);
911 :
912 10 : return vr_fabric_input(vif, pkt, &fmd, vlan_id);
913 : }
914 :
915 : static int
916 11 : vhost_tx(struct vr_interface *vif, struct vr_packet *pkt,
917 : struct vr_forwarding_md *fmd)
918 : {
919 : int ret;
920 11 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
921 11 : unsigned short eth_proto, pull_len = 0;
922 : unsigned char *new_eth, *eth;
923 : struct vr_eth *eth_hdr;
924 : struct vr_vlan_hdr *vlan;
925 : struct vr_interface *in_vif;
926 11 : struct vr_ip *ip = (struct vr_ip *) pkt_network_header(pkt);
927 :
928 11 : stats->vis_obytes += pkt_len(pkt);
929 11 : stats->vis_opackets++;
930 :
931 11 : if (vif->vif_type == VIF_TYPE_XEN_LL_HOST)
932 0 : memcpy(pkt_data(pkt), vif->vif_mac, sizeof(vif->vif_mac));
933 11 : else if (vif->vif_type == VIF_TYPE_HOST) {
934 11 : in_vif = pkt->vp_if;
935 22 : if (!hif_ops->hif_get_encap ||
936 11 : (hif_ops->hif_get_encap(in_vif) == VIF_ENCAP_TYPE_ETHER)) {
937 : /* Untag any tagged packets */
938 11 : eth = pkt_data(pkt);
939 11 : eth_proto = ntohs(*(unsigned short *)(eth + VR_ETHER_PROTO_OFF));
940 11 : while (eth_proto == VR_ETH_PROTO_VLAN) {
941 0 : vlan = (struct vr_vlan_hdr *)(pkt_data(pkt) + pull_len +
942 : VR_ETHER_HLEN);
943 0 : eth_proto = ntohs(vlan->vlan_proto);
944 0 : pull_len += sizeof(*vlan);
945 : }
946 :
947 : /* If there are any vlan tags */
948 11 : if (pull_len) {
949 0 : new_eth = pkt_pull(pkt, pull_len);
950 0 : if (!new_eth) {
951 0 : PKT_LOG(VP_DROP_PULL, pkt, 0, VR_INTERFACE_C, __LINE__);
952 0 : vr_pfree(pkt, VP_DROP_PULL);
953 0 : return 0;
954 : }
955 0 : memmove(new_eth, eth, (2 * VR_ETHER_ALEN));
956 : }
957 : /*
958 : * Rewrite dst MAC for the link local (169.254/16) addresses.
959 : * The replies from VMs are destined to VRRP MAC, hence
960 : * they are discarded by the IP stack.
961 : * For the Linux platform we fix it by setting skb->pkt_type
962 : * to PACKET_HOST in linux_if_rx() function.
963 : * The following code fixes MACs for all the platforms.
964 : */
965 11 : if (vif_is_virtual(in_vif)) {
966 1 : eth_hdr = (struct vr_eth *)pkt_data(pkt);
967 1 : memcpy(eth_hdr->eth_dmac, vif->vif_mac, VR_ETHER_ALEN);
968 : }
969 : } else {
970 0 : eth_hdr = (struct vr_eth *)pkt_push(pkt, VR_ETHER_HLEN);
971 0 : memcpy(eth_hdr->eth_dmac, vif->vif_mac, VR_ETHER_ALEN);
972 0 : memcpy(eth_hdr->eth_smac, vif->vif_mac, VR_ETHER_ALEN);
973 0 : if (pkt->vp_type == VP_TYPE_IP6)
974 0 : eth_hdr->eth_proto = htons(VR_ETH_PROTO_IP6);
975 : else
976 0 : eth_hdr->eth_proto = htons(VR_ETH_PROTO_IP);
977 : }
978 11 : if (!strncmp(vif->vif_name, "vhost0", 5)) {
979 8 : if (ntohl(ip->ip_daddr) == vif->vif_l3mh_loip) {
980 0 : eth_hdr = (struct vr_eth *)pkt_data(pkt);
981 0 : memcpy(eth_hdr->eth_dmac, vif->vif_mac, VR_ETHER_ALEN);
982 : }
983 : }
984 : }
985 :
986 11 : vif_mirror(vif, pkt, fmd, vif->vif_flags & VIF_FLAG_MIRROR_TX);
987 :
988 11 : ret = hif_ops->hif_rx(vif, pkt);
989 11 : if (ret < 0) {
990 0 : ret = 0;
991 0 : stats->vis_oerrors++;
992 : }
993 :
994 11 : return ret;
995 : }
996 :
997 : static int
998 50 : vhost_drv_del(struct vr_interface *vif)
999 : {
1000 :
1001 50 : vif->vif_tx = vif_discard_tx;
1002 50 : vif->vif_rx = vif_discard_rx;
1003 :
1004 50 : return hif_ops->hif_del(vif);
1005 : }
1006 :
1007 : static int
1008 50 : vhost_drv_add(struct vr_interface *vif,
1009 : vr_interface_req *vifr)
1010 : {
1011 50 : int ret = 0, i;
1012 :
1013 50 : if (!vif->vif_mtu)
1014 0 : vif->vif_mtu = 1514;
1015 :
1016 50 : vif->vif_set_rewrite = vif_cmn_rewrite;
1017 50 : vif->vif_tx = vhost_tx;
1018 50 : vif->vif_rx = vhost_rx;
1019 50 : vif->vif_mac_request = vhost_mac_request;
1020 :
1021 50 : if (!vifr) {
1022 0 : vif->vif_l3mh_loip = 0;
1023 : } else {
1024 50 : vif->vif_l3mh_loip = vifr->vifr_loopback_ip;
1025 : }
1026 :
1027 50 : ret = hif_ops->hif_add(vif);
1028 50 : if (ret)
1029 0 : return ret;
1030 : /*
1031 : * add tap to the corresponding physical interface, now
1032 : * that vhost is functional
1033 : */
1034 200 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
1035 150 : if (vif->vif_bridge[i]) {
1036 50 : ret = hif_ops->hif_add_tap(vif->vif_bridge[i], vifr);
1037 50 : if (ret)
1038 0 : return ret;
1039 : }
1040 : }
1041 :
1042 50 : return 0;
1043 : }
1044 : /* end vhost driver */
1045 :
1046 : /* vlan driver */
1047 : static int
1048 0 : vlan_rx(struct vr_interface *vif, struct vr_packet *pkt,
1049 : unsigned short vlan_id __attribute__unused__)
1050 : {
1051 : int8_t tos;
1052 0 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
1053 : struct vr_forwarding_md fmd;
1054 :
1055 0 : vr_init_forwarding_md(&fmd);
1056 0 : pkt->vp_if = vif;
1057 :
1058 0 : stats->vis_ibytes += pkt_len(pkt);
1059 0 : stats->vis_ipackets++;
1060 :
1061 0 : if (!(vif->vif_flags & VIF_FLAG_MIRROR_NOTAG))
1062 0 : vif_mirror(vif, pkt, NULL, vif->vif_flags & VIF_FLAG_MIRROR_RX);
1063 :
1064 0 : tos = vr_vlan_get_tos(pkt_data(pkt));
1065 0 : if (tos >= 0)
1066 0 : pkt->vp_priority = tos;
1067 :
1068 0 : if (vr_untag_pkt(pkt)) {
1069 0 : stats->vis_ierrors++;
1070 0 : PKT_LOG(VP_DROP_PULL, pkt, 0, VR_INTERFACE_C, __LINE__);
1071 0 : vr_pfree(pkt, VP_DROP_PULL);
1072 0 : return 0;
1073 : }
1074 :
1075 0 : vr_pset_data(pkt, pkt->vp_data);
1076 :
1077 0 : if (vif->vif_flags & VIF_FLAG_MIRROR_NOTAG)
1078 0 : vif_mirror(vif, pkt, NULL, vif->vif_flags & VIF_FLAG_MIRROR_RX);
1079 :
1080 0 : vr_offload_packet_parse(pkt);
1081 :
1082 0 : return vr_virtual_input(vif->vif_vrf, vif, pkt, &fmd, VLAN_ID_INVALID);
1083 : }
1084 :
1085 :
1086 : static int
1087 0 : vlan_tx(struct vr_interface *vif, struct vr_packet *pkt,
1088 : struct vr_forwarding_md *fmd)
1089 : {
1090 0 : bool force_tag = false;
1091 0 : int ret = 0;
1092 : struct vr_interface *pvif;
1093 0 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
1094 :
1095 0 : if (!vr_pkt_is_gro(pkt)) {
1096 0 : stats->vis_obytes += pkt_len(pkt);
1097 0 : stats->vis_opackets++;
1098 : }
1099 :
1100 0 : if (vif->vif_flags & VIF_FLAG_MIRROR_NOTAG)
1101 0 : vif_mirror(vif, pkt, fmd, vif->vif_flags & VIF_FLAG_MIRROR_TX);
1102 :
1103 0 : if (vif_is_vlan(vif)) {
1104 0 : if (vif->vif_ovlan_id) {
1105 : /*
1106 : * If the packet is already received with Tag on interface,
1107 : * we can force this tag, as double tag is intended
1108 : */
1109 0 : if (fmd->fmd_vlan != VLAN_ID_INVALID)
1110 0 : force_tag = true;
1111 :
1112 0 : if (vr_tag_pkt(&pkt, vif->vif_ovlan_id, force_tag)) {
1113 0 : PKT_LOG(VP_DROP_INVALID_IF, pkt, 0, VR_INTERFACE_C, __LINE__);
1114 0 : goto drop;
1115 : }
1116 0 : vr_pset_data(pkt, pkt->vp_data);
1117 : } else {
1118 0 : vr_vlan_set_priority(pkt);
1119 : }
1120 : }
1121 :
1122 0 : if (!(vif->vif_flags & VIF_FLAG_MIRROR_NOTAG))
1123 0 : vif_mirror(vif, pkt, fmd, vif->vif_flags & VIF_FLAG_MIRROR_TX);
1124 :
1125 0 : pvif = vif->vif_parent;
1126 0 : if (!pvif) {
1127 0 : PKT_LOG(VP_DROP_INVALID_IF, pkt, 0, VR_INTERFACE_C, __LINE__);
1128 0 : goto drop;
1129 : }
1130 :
1131 0 : ret = pvif->vif_tx(pvif, pkt, fmd);
1132 0 : if (ret < 0) {
1133 0 : ret = 0;
1134 0 : PKT_LOG(VP_DROP_INVALID_IF, pkt, 0, VR_INTERFACE_C, __LINE__);
1135 0 : goto drop;
1136 : }
1137 :
1138 0 : return ret;
1139 :
1140 0 : drop:
1141 0 : vr_pfree(pkt, VP_DROP_INVALID_IF);
1142 0 : stats->vis_oerrors++;
1143 :
1144 0 : return ret;
1145 : }
1146 :
1147 : static int
1148 17 : vlan_sub_interface_manage(struct vr_interface *pvif,
1149 : struct vr_interface *vif, int src_mac_num, uint8_t *src_macs)
1150 : {
1151 : int i, j, ret;
1152 : uint8_t *vif_mac_entry, *vifr_mac_entry, *free_entry;
1153 :
1154 17 : if (!vif || !pvif || !vif->vif_src_mac)
1155 17 : return 0;
1156 :
1157 0 : vif_mac_entry = vif->vif_src_mac;
1158 0 : for (i = 0; i < VIF_SRC_MACS; i++) {
1159 0 : if (!IS_MAC_ZERO(vif_mac_entry)) {
1160 0 : vifr_mac_entry = src_macs;
1161 0 : for (j = 0; j < src_mac_num; j++) {
1162 0 : if (VR_MAC_CMP(vifr_mac_entry, vif_mac_entry))
1163 0 : break;
1164 0 : vifr_mac_entry += VR_ETHER_ALEN;
1165 : }
1166 0 : if (j == src_mac_num) {
1167 0 : ret = vif_bridge_delete(pvif, vif, vif_mac_entry);
1168 0 : if (!ret)
1169 0 : return ret;
1170 :
1171 0 : VR_MAC_RESET(vif_mac_entry);
1172 : }
1173 : }
1174 0 : vif_mac_entry += VR_ETHER_ALEN;
1175 : }
1176 :
1177 0 : vifr_mac_entry = src_macs;
1178 0 : for (j = 0; j < src_mac_num; j++) {
1179 0 : if (!IS_MAC_ZERO(vifr_mac_entry)) {
1180 :
1181 0 : vif_mac_entry = vif->vif_src_mac;
1182 0 : free_entry = NULL;
1183 :
1184 0 : for (i = 0; i < VIF_SRC_MACS; i++) {
1185 :
1186 0 : if (!IS_MAC_ZERO(vif_mac_entry)) {
1187 0 : if (VR_MAC_CMP(vifr_mac_entry, vif_mac_entry))
1188 0 : break;
1189 0 : } else if (!free_entry) {
1190 0 : free_entry = vif_mac_entry;
1191 : }
1192 :
1193 0 : vif_mac_entry += VR_ETHER_ALEN;
1194 : }
1195 :
1196 0 : if (i == VIF_SRC_MACS) {
1197 0 : if (!free_entry)
1198 0 : return -ENOSPC;
1199 0 : ret = vif_bridge_add(pvif, vif, vifr_mac_entry);
1200 0 : if (ret)
1201 0 : return ret;
1202 0 : VR_MAC_COPY(free_entry, vifr_mac_entry);
1203 : }
1204 : }
1205 :
1206 0 : vifr_mac_entry += VR_ETHER_ALEN;
1207 : }
1208 :
1209 :
1210 0 : return 0;
1211 : }
1212 :
1213 : static int
1214 0 : vlan_drv_del(struct vr_interface *vif)
1215 : {
1216 0 : int ret = 0;
1217 : struct vr_interface *pvif;
1218 :
1219 0 : pvif = vif->vif_parent;
1220 0 : if (!pvif)
1221 0 : return 0;
1222 :
1223 0 : if (vif->vif_src_mac) {
1224 0 : vlan_sub_interface_manage(pvif, vif, 0, NULL);
1225 : } else {
1226 0 : if (pvif->vif_sub_interfaces &&
1227 0 : (pvif->vif_sub_interfaces[vif->vif_vlan_id] == vif)) {
1228 0 : pvif->vif_sub_interfaces[vif->vif_vlan_id] = NULL;
1229 : } else {
1230 0 : ret = -EINVAL;
1231 : }
1232 : }
1233 :
1234 0 : if (pvif->vif_driver->drv_delete_sub_interface)
1235 0 : pvif->vif_driver->drv_delete_sub_interface(pvif, vif);
1236 :
1237 0 : if (vif->vif_src_mac) {
1238 0 : vr_free(vif->vif_src_mac, VR_INTERFACE_MAC_OBJECT);
1239 0 : vif->vif_src_mac = NULL;
1240 : }
1241 :
1242 0 : return ret;
1243 : }
1244 :
1245 : static int
1246 0 : vlan_drv_add(struct vr_interface *vif, vr_interface_req *vifr)
1247 : {
1248 0 : int ret = 0;
1249 0 : struct vr_interface *pvif = NULL;
1250 :
1251 0 : if ((unsigned int)(vifr->vifr_parent_vif_idx) > VR_MAX_INTERFACES)
1252 0 : return -EINVAL;
1253 :
1254 0 : if (((unsigned short)(vifr->vifr_vlan_id) >= VLAN_ID_MAX) ||
1255 0 : ((unsigned short)(vifr->vifr_ovlan_id) >= VLAN_ID_MAX))
1256 0 : return -EINVAL;
1257 :
1258 0 : pvif = vrouter_get_interface(vifr->vifr_rid, vifr->vifr_parent_vif_idx);
1259 0 : if (!pvif)
1260 0 : return -EINVAL;
1261 :
1262 0 : if (vifr->vifr_src_mac_size && vifr->vifr_src_mac) {
1263 0 : if (vifr->vifr_src_mac_size % VR_ETHER_ALEN)
1264 0 : return -EINVAL;
1265 0 : if ((vifr->vifr_src_mac_size / VR_ETHER_ALEN) > VIF_SRC_MACS)
1266 0 : return -EINVAL;
1267 0 : if (!vif->vif_src_mac) {
1268 0 : vif->vif_src_mac = vr_zalloc((VIF_SRC_MACS * VR_ETHER_ALEN), VR_INTERFACE_MAC_OBJECT);
1269 0 : if (!vif->vif_src_mac)
1270 0 : return -ENOMEM;
1271 : }
1272 :
1273 0 : if (!pvif->vif_btable) {
1274 0 : ret = vif_bridge_init(pvif);
1275 0 : if (ret)
1276 0 : return ret;
1277 : }
1278 : } else {
1279 0 : if(!pvif->vif_sub_interfaces) {
1280 0 : pvif->vif_sub_interfaces = vr_zalloc(
1281 : VLAN_ID_MAX * sizeof(struct vr_interface *),
1282 : VR_INTERFACE_OBJECT);
1283 0 : if (!pvif->vif_sub_interfaces)
1284 0 : return -ENOMEM;
1285 : }
1286 : }
1287 :
1288 :
1289 0 : if (!vif->vif_mtu)
1290 0 : vif->vif_mtu = 1514;
1291 :
1292 0 : vif->vif_set_rewrite = vif_cmn_rewrite;
1293 0 : vif->vif_tx = vlan_tx;
1294 0 : vif->vif_rx = vlan_rx;
1295 0 : vif->vif_mac_request = vm_mac_request;
1296 0 : vif->vif_vlan_id = vifr->vifr_vlan_id;
1297 0 : vif->vif_ovlan_id = vifr->vifr_ovlan_id;
1298 :
1299 :
1300 0 : vif->vif_parent = pvif;
1301 :
1302 0 : if (!pvif->vif_driver->drv_add_sub_interface)
1303 0 : return -EINVAL;
1304 :
1305 0 : ret = pvif->vif_driver->drv_add_sub_interface(pvif, vif);
1306 0 : if (ret)
1307 0 : return ret;
1308 :
1309 0 : if (!vif->vif_src_mac) {
1310 0 : if (pvif->vif_sub_interfaces[vif->vif_vlan_id])
1311 0 : return -EEXIST;
1312 0 : pvif->vif_sub_interfaces[vif->vif_vlan_id] = vif;
1313 : } else {
1314 0 : return vlan_sub_interface_manage(pvif, vif,
1315 0 : (vifr->vifr_src_mac_size / VR_ETHER_ALEN), vifr->vifr_src_mac);
1316 :
1317 : }
1318 :
1319 0 : return 0;
1320 : }
1321 : /* end vlan driver */
1322 :
1323 : /* eth driver */
1324 : static int
1325 0 : vm_srx(struct vr_interface *vif, struct vr_packet *pkt,
1326 : unsigned short vlan_id)
1327 : {
1328 : unsigned short vrf;
1329 0 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
1330 : struct vr_forwarding_md fmd;
1331 :
1332 0 : vr_init_forwarding_md(&fmd);
1333 :
1334 0 : stats->vis_ibytes += pkt_len(pkt);
1335 0 : stats->vis_ipackets++;
1336 :
1337 0 : if (vlan_id >= VIF_VRF_TABLE_ENTRIES)
1338 0 : vrf = vif->vif_vrf;
1339 : else
1340 0 : vrf = vif->vif_vrf_table[vlan_id].va_vrf;
1341 :
1342 0 : vif_mirror(vif, pkt, &fmd, vif->vif_flags & VIF_FLAG_MIRROR_RX);
1343 :
1344 0 : return vr_virtual_input(vrf, vif, pkt, &fmd, vlan_id);
1345 : }
1346 :
1347 : static mac_response_t
1348 7 : vm_mac_request(struct vr_interface *vif, struct vr_packet *pkt,
1349 : struct vr_forwarding_md *fmd, unsigned char *dmac)
1350 : {
1351 7 : if (pkt->vp_type == VP_TYPE_ARP) {
1352 5 : return vm_arp_request(vif, pkt, fmd, dmac);
1353 2 : } else if (pkt->vp_type == VP_TYPE_IP6) {
1354 2 : return vm_neighbor_request(vif, pkt, fmd, dmac);
1355 : }
1356 :
1357 0 : return MR_DROP;
1358 : }
1359 :
1360 : static int
1361 126 : vm_rx(struct vr_interface *vif, struct vr_packet *pkt,
1362 : unsigned short vlan_id)
1363 : {
1364 : struct vr_forwarding_md fmd;
1365 126 : struct vr_interface *sub_vif = NULL;
1366 126 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
1367 126 : struct vr_eth *eth = (struct vr_eth *)pkt_data(pkt);
1368 :
1369 126 : vr_init_forwarding_md(&fmd);
1370 126 : fmd.fmd_dvrf = vif->vif_vrf;
1371 :
1372 126 : vif_mirror(vif, pkt, &fmd, vif->vif_flags & VIF_FLAG_MIRROR_RX);
1373 :
1374 126 : if (vlan_id != VLAN_ID_INVALID && vlan_id < VLAN_ID_MAX) {
1375 0 : if (vif->vif_btable) {
1376 0 : sub_vif = vif_bridge_get_sub_interface(vif->vif_btable, vlan_id,
1377 0 : eth->eth_smac);
1378 : } else {
1379 0 : if (vif->vif_sub_interfaces)
1380 0 : sub_vif = vif->vif_sub_interfaces[vlan_id];
1381 : }
1382 :
1383 0 : if (sub_vif)
1384 0 : return sub_vif->vif_rx(sub_vif, pkt, VLAN_ID_INVALID);
1385 : }
1386 :
1387 : /*
1388 : * there is a requirement that stats be not counted in both the
1389 : * underlying interface and in the sub-interface (double count).
1390 : * this behavior is a specific requirement for VM interfaces since
1391 : * the VM interface and the sub-interface on top are considered
1392 : * two different VMIs and can be in two different VRFs. Counting
1393 : * stats in both interfaces will wrongly put statistics in a VRF
1394 : * where the statistics should not have been counted. hence the
1395 : * stats count block is below and not the first thing that we do
1396 : * in this function.
1397 : */
1398 126 : stats->vis_ibytes += pkt_len(pkt);
1399 126 : stats->vis_ipackets++;
1400 :
1401 126 : vr_offload_packet_parse(pkt);
1402 :
1403 126 : return vr_virtual_input(vif->vif_vrf, vif, pkt, &fmd, vlan_id);
1404 : }
1405 :
1406 : static int
1407 0 : tun_rx(struct vr_interface *vif, struct vr_packet *pkt,
1408 : unsigned short vlan_id)
1409 : {
1410 : unsigned char first_b;
1411 : struct vr_forwarding_md fmd;
1412 0 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
1413 :
1414 0 : stats->vis_ibytes += pkt_len(pkt);
1415 0 : stats->vis_ipackets++;
1416 :
1417 0 : if (vif_mode_xconnect(vif))
1418 0 : pkt->vp_flags |= VP_FLAG_TO_ME;
1419 :
1420 0 : first_b = *pkt_data(pkt);
1421 0 : first_b &= 0xf0;
1422 :
1423 0 : switch (first_b) {
1424 0 : case 0x40:
1425 0 : pkt->vp_type = VP_TYPE_IP;
1426 0 : break;
1427 :
1428 0 : case 0x60:
1429 0 : pkt->vp_type = VP_TYPE_IP6;
1430 0 : break;
1431 :
1432 0 : default:
1433 0 : PKT_LOG(VP_DROP_INVALID_PACKET, pkt, 0, VR_INTERFACE_C, __LINE__);
1434 0 : vr_pfree(pkt, VP_DROP_INVALID_PACKET);
1435 0 : return 0;
1436 : }
1437 :
1438 0 : pkt_set_network_header(pkt, pkt->vp_data);
1439 :
1440 0 : vr_init_forwarding_md(&fmd);
1441 0 : fmd.fmd_vlan = vlan_id;
1442 0 : fmd.fmd_dvrf = vif->vif_vrf;
1443 :
1444 0 : vif_mirror(vif, pkt, &fmd, vif->vif_flags & VIF_FLAG_MIRROR_RX);
1445 :
1446 0 : vr_l3_input(pkt, &fmd);
1447 :
1448 0 : return 0;
1449 : }
1450 :
1451 : /*
1452 : * This function is to handle the decrypted Rx packet. The
1453 : * ipsec encrypted packet is sent up the stack where the
1454 : * linux IPSec kernel handles it. Upon decrypting it
1455 : * the packet is received by the VTI interface, which is
1456 : * the L3 interface that is plumbed to the vrouter.
1457 : * This packet is the L3VPN packet to be processed by vrouter.
1458 : *
1459 : */
1460 : static int
1461 0 : ipsec_rx(struct vr_interface *vif, struct vr_packet *pkt,
1462 : unsigned short vlan_id)
1463 : {
1464 0 : struct vrouter *router = vrouter_get(0);
1465 : int i;
1466 0 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
1467 0 : if (router->vr_eth_if[i] &&
1468 0 : (memcmp(vif->vif_mac, router->vr_eth_if[i]->vif_mac, VR_ETHER_ALEN) == 0)) {
1469 0 : pkt->vp_if = router->vr_eth_if[i];
1470 0 : break;
1471 : }
1472 : }
1473 0 : return eth_rx(vif, pkt, vlan_id);
1474 : }
1475 :
1476 : static int
1477 56 : eth_set_rewrite(struct vr_interface *vif, struct vr_packet **pkt,
1478 : struct vr_forwarding_md *fmd, unsigned char *rewrite,
1479 : unsigned short len)
1480 : {
1481 56 : if (!len)
1482 0 : return 0;
1483 :
1484 : /*
1485 : * Retain the original headerof the HostOs if the packet is not
1486 : * tunneled packet and not from Agent. Otherwise, apply the new
1487 : * rewrite data.
1488 : * Apply rewrite data even when dmac of the pkt is vhost mac
1489 : * which implies pkt is routed through vrouter
1490 : */
1491 56 : if (((*pkt)->vp_if->vif_type == VIF_TYPE_HOST) &&
1492 2 : (!((*pkt)->vp_flags & VP_FLAG_FROM_DP)) &&
1493 2 : (fmd->fmd_ecmp_src_nh_index == -1) &&
1494 2 : (((*pkt)->vp_type == VP_TYPE_IP) || ((*pkt)->vp_type == VP_TYPE_IP6)) &&
1495 1 : (memcmp((*pkt)->vp_if->vif_mac, (pkt_data(*pkt) - VR_ETHER_HLEN), VR_ETHER_ALEN) != 0)) {
1496 1 : vr_preset(*pkt);
1497 1 : return 0;
1498 : }
1499 :
1500 55 : return vif_cmn_rewrite(vif, pkt, fmd, rewrite, len);
1501 : }
1502 :
1503 : static mac_response_t
1504 3 : eth_mac_request(struct vr_interface *vif, struct vr_packet *pkt,
1505 : struct vr_forwarding_md *fmd, unsigned char *dmac)
1506 : {
1507 3 : bool underlay_arp = false, underlay_ipv6 = false;
1508 3 : struct vr_arp *sarp = NULL;
1509 : struct vr_icmp *icmp6;
1510 3 : bool is_ipv6_nd_packet = false;
1511 : mac_response_t mr;
1512 :
1513 3 : if (vif_mode_xconnect(vif))
1514 1 : return MR_XCONNECT;
1515 :
1516 : /*
1517 : * If there is a label or if the vrf is different, it is meant for VM's
1518 : */
1519 2 : is_ipv6_nd_packet = vr_is_ipv6_nd_packet(pkt);
1520 2 : if (pkt->vp_type == VP_TYPE_ARP)
1521 1 : sarp = (struct vr_arp *)pkt_data(pkt);
1522 1 : else if (is_ipv6_nd_packet)
1523 1 : icmp6 = (struct vr_icmp *)pkt_data(pkt);
1524 :
1525 2 : if ((fmd->fmd_label == -1) && (fmd->fmd_dvrf == vif->vif_vrf)) {
1526 2 : if (pkt->vp_type == VP_TYPE_ARP) {
1527 1 : underlay_arp = true;
1528 1 : if (vr_grat_arp(sarp))
1529 0 : return MR_TRAP_X;
1530 1 : } else if (is_ipv6_nd_packet) {
1531 1 : underlay_ipv6 = true;
1532 : }
1533 : }
1534 :
1535 2 : mr = vm_mac_request(vif, pkt, fmd, dmac);
1536 2 : if (underlay_arp && (mr != MR_XCONNECT) && (mr != MR_PROXY)) {
1537 0 : vr_printf("Vrouter: Vhost arp request Mr %d Dst %x src %x"
1538 : " converting to Xconnect\n",
1539 : mr, sarp->arp_dpa, sarp->arp_spa);
1540 :
1541 0 : mr = MR_XCONNECT;
1542 2 : } else if (underlay_ipv6 && (mr != MR_XCONNECT) && (mr != MR_PROXY)) {
1543 1 : mr = MR_XCONNECT;
1544 : }
1545 :
1546 2 : return mr;
1547 : }
1548 :
1549 :
1550 :
1551 : static int
1552 20 : eth_rx(struct vr_interface *vif, struct vr_packet *pkt,
1553 : unsigned short vlan_id)
1554 : {
1555 : struct vr_forwarding_md fmd;
1556 20 : struct vr_interface *sub_vif = NULL;
1557 20 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
1558 20 : struct vr_eth *eth = (struct vr_eth *)pkt_data(pkt);
1559 :
1560 20 : vr_init_forwarding_md(&fmd);
1561 :
1562 20 : stats->vis_ibytes += pkt_len(pkt);
1563 20 : stats->vis_ipackets++;
1564 :
1565 20 : vif_mirror(vif, pkt, &fmd, vif->vif_flags & VIF_FLAG_MIRROR_RX);
1566 :
1567 : /*
1568 : * please see the text on xconnect mode
1569 : *
1570 : * since we would like the packets to reach the VMs (if they were
1571 : * destined to in the first place), packets have to traverse the
1572 : * stack. so, just mark a flag suggesting that packet is destined
1573 : * for the vrouter and force the vrouter to receive the packet
1574 : */
1575 20 : if (vif_mode_xconnect(vif))
1576 2 : pkt->vp_flags |= VP_FLAG_TO_ME;
1577 :
1578 20 : if ((vlan_id == VLAN_ID_INVALID) &&
1579 20 : (vif->vif_flags & VIF_FLAG_NATIVE_VLAN_TAG))
1580 0 : vlan_id = 0;
1581 :
1582 20 : if (vlan_id != VLAN_ID_INVALID && vlan_id < VLAN_ID_MAX) {
1583 0 : if (vif->vif_btable) {
1584 0 : sub_vif = vif_bridge_get_sub_interface(vif->vif_btable, vlan_id,
1585 0 : eth->eth_smac);
1586 : } else {
1587 0 : if (vif->vif_sub_interfaces)
1588 0 : sub_vif = vif->vif_sub_interfaces[vlan_id];
1589 : }
1590 :
1591 0 : if (sub_vif)
1592 0 : return sub_vif->vif_rx(sub_vif, pkt, VLAN_ID_INVALID);
1593 : }
1594 :
1595 20 : vr_offload_packet_parse(pkt);
1596 :
1597 20 : return vr_fabric_input(vif, pkt, &fmd, vlan_id);
1598 : }
1599 :
1600 : static int
1601 126 : eth_tx(struct vr_interface *vif, struct vr_packet *pkt,
1602 : struct vr_forwarding_md *fmd)
1603 : {
1604 126 : bool stats_count = true, from_subvif = false, force_tag = true;
1605 : int ret, handled;
1606 : uint16_t vlan_id;
1607 :
1608 126 : struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu);
1609 :
1610 126 : vif_mirror(vif, pkt, fmd, vif->vif_flags & VIF_FLAG_MIRROR_TX);
1611 :
1612 126 : if (vif_is_virtual(vif)) {
1613 60 : handled = vif_plug_mac_request(vif, pkt, fmd);
1614 60 : if (handled)
1615 0 : return 0;
1616 :
1617 : /*
1618 : * GRO packets come here twice - once with VP_FLAG_GRO set and
1619 : * once without the flag set. Don't count them twice. Also,
1620 : * if the packet came from the sub interface on top, we should
1621 : * not be counting them twice. The way we determine that the
1622 : * packet has come from sub-interface is by looking at nexthop
1623 : * and checking whether nh_dev is not the same as vif, or in
1624 : * the absence of nh and the packet ingressed from agent interface,
1625 : * the vlan id is set.
1626 : */
1627 60 : if (vr_pkt_is_gro(pkt))
1628 0 : stats_count = false;
1629 :
1630 60 : if ((pkt->vp_nh && (pkt->vp_nh->nh_dev != vif)) ||
1631 60 : ((pkt->vp_if->vif_type == VIF_TYPE_AGENT) &&
1632 0 : (fmd->fmd_vlan != VLAN_ID_INVALID))) {
1633 0 : from_subvif = true;
1634 0 : stats_count = false;
1635 : }
1636 66 : } else if (vif_is_fabric(vif)) {
1637 66 : vlan_id = vr_fmd_get_mirror_vlan(fmd);
1638 66 : if (vlan_id != FMD_MIRROR_INVALID_DATA) {
1639 0 : vr_tag_pkt(&pkt, vlan_id, force_tag);
1640 : }
1641 : }
1642 :
1643 126 : if (stats_count) {
1644 126 : stats->vis_obytes += pkt_len(pkt);
1645 126 : stats->vis_opackets++;
1646 : }
1647 :
1648 126 : ret = hif_ops->hif_tx(vif, pkt);
1649 126 : if (ret != 0) {
1650 1 : if (!from_subvif)
1651 1 : ret = 0;
1652 :
1653 1 : if (stats_count)
1654 1 : stats->vis_oerrors++;
1655 : }
1656 :
1657 126 : return ret;
1658 : }
1659 :
1660 : static int
1661 240 : eth_drv_del(struct vr_interface *vif)
1662 : {
1663 : int ret;
1664 :
1665 240 : hif_ops->hif_del_tap(vif);
1666 :
1667 240 : vif->vif_tx = vif_discard_tx;
1668 240 : vif->vif_rx = vif_discard_rx;
1669 :
1670 240 : ret = hif_ops->hif_del(vif);
1671 240 : if (vif->vif_flags & VIF_FLAG_SERVICE_IF)
1672 0 : vr_interface_service_disable(vif);
1673 240 : return ret;
1674 : }
1675 :
1676 :
1677 : static int
1678 0 : eth_drv_del_sub_interface(struct vr_interface *pvif, struct vr_interface *vif)
1679 : {
1680 :
1681 0 : if (vif->vif_parent == pvif) {
1682 0 : vif->vif_parent = NULL;
1683 0 : vrouter_put_interface(pvif);
1684 : }
1685 0 : hif_ops->hif_del(vif);
1686 :
1687 0 : return 0;
1688 : }
1689 :
1690 : static int
1691 0 : eth_drv_add_sub_interface(struct vr_interface *pvif, struct vr_interface *vif)
1692 : {
1693 0 : return hif_ops->hif_add(vif);
1694 : }
1695 :
1696 : static int
1697 240 : eth_drv_add(struct vr_interface *vif,
1698 : vr_interface_req *vifr)
1699 : {
1700 240 : int ret = 0;
1701 :
1702 240 : if (!vif->vif_mtu) {
1703 0 : vif->vif_mtu = 9160;
1704 0 : if (vif->vif_type == VIF_TYPE_PHYSICAL)
1705 0 : vif->vif_mtu = 1514;
1706 : }
1707 :
1708 240 : if (vif->vif_type != VIF_TYPE_STATS) {
1709 240 : vif->vif_tx = eth_tx;
1710 :
1711 240 : if (vif_is_virtual(vif)) {
1712 168 : vif->vif_rx = vm_rx;
1713 168 : vif->vif_set_rewrite = vif_cmn_rewrite;
1714 168 : vif->vif_mac_request = vm_mac_request;
1715 : } else {
1716 72 : vif->vif_rx = eth_rx;
1717 72 : vif->vif_set_rewrite = eth_set_rewrite;
1718 72 : vif->vif_mac_request = eth_mac_request;
1719 : }
1720 : }
1721 :
1722 240 : if (vif->vif_flags & VIF_FLAG_SERVICE_IF) {
1723 0 : ret = vr_interface_service_enable(vif);
1724 0 : if (ret)
1725 0 : goto exit_add;
1726 : }
1727 :
1728 240 : ret = hif_ops->hif_add(vif);
1729 240 : if (ret)
1730 0 : goto exit_add;
1731 :
1732 312 : if ((vif->vif_type == VIF_TYPE_PHYSICAL) &&
1733 72 : (hif_ops->hif_get_encap(vif) == VIF_ENCAP_TYPE_L3)) {
1734 0 : vif->vif_rx = tun_rx;
1735 312 : } else if ((vif->vif_type == VIF_TYPE_PHYSICAL) &&
1736 72 : ((hif_ops->hif_get_encap(vif) == VIF_ENCAP_TYPE_L3_DECRYPT))) {
1737 0 : vif->vif_rx = ipsec_rx;
1738 : }
1739 :
1740 : /*
1741 : * as soon as we add the tap, packets will start traversing vrouter.
1742 : * now, without a vhost interface getting added, such packets are
1743 : * useless. Also, once reset happens, the physical interface sends
1744 : * packets directly to vhost interface, bypassing vrouter. If we tap
1745 : * here, such packets will be blackholed. hence, do not tap the interface
1746 : * if the interface is set to be associated with a vhost interface.
1747 : */
1748 : /*
1749 : * RX of the decrypted packet is handled.
1750 : */
1751 240 : if ((!(vif->vif_flags & VIF_FLAG_VHOST_PHYS)) ||
1752 68 : (vif->vif_bridge[0]) || (hif_ops->hif_get_encap(vif) == VIF_ENCAP_TYPE_L3_DECRYPT)) {
1753 172 : ret = hif_ops->hif_add_tap(vif, vifr);
1754 172 : if (ret)
1755 0 : hif_ops->hif_del(vif);
1756 : }
1757 :
1758 240 : exit_add:
1759 240 : if (ret)
1760 0 : if (vif->vif_flags & VIF_FLAG_SERVICE_IF)
1761 0 : vr_interface_service_disable(vif);
1762 :
1763 240 : return ret;
1764 : }
1765 : /* end eth driver */
1766 :
1767 : static struct vr_interface_driver vif_drivers[VIF_TYPE_MAX] = {
1768 : [VIF_TYPE_HOST] = {
1769 : .drv_add = vhost_drv_add,
1770 : .drv_delete = vhost_drv_del,
1771 : },
1772 : [VIF_TYPE_XEN_LL_HOST] = {
1773 : .drv_add = vhost_drv_add,
1774 : .drv_delete = vhost_drv_del,
1775 : },
1776 : [VIF_TYPE_GATEWAY] = {
1777 : .drv_add = vhost_drv_add,
1778 : .drv_delete = vhost_drv_del,
1779 : },
1780 : [VIF_TYPE_AGENT] = {
1781 : .drv_add = agent_drv_add,
1782 : .drv_delete = agent_drv_del,
1783 : },
1784 : [VIF_TYPE_PHYSICAL] = {
1785 : .drv_add = eth_drv_add,
1786 : .drv_delete = eth_drv_del,
1787 : .drv_add_sub_interface = eth_drv_add_sub_interface,
1788 : .drv_delete_sub_interface = eth_drv_del_sub_interface,
1789 : },
1790 : [VIF_TYPE_VIRTUAL] = {
1791 : .drv_add = eth_drv_add,
1792 : .drv_delete = eth_drv_del,
1793 : .drv_add_sub_interface = eth_drv_add_sub_interface,
1794 : .drv_delete_sub_interface = eth_drv_del_sub_interface,
1795 : },
1796 : [VIF_TYPE_VIRTUAL_VLAN] = {
1797 : .drv_add = vlan_drv_add,
1798 : .drv_delete = vlan_drv_del,
1799 : },
1800 : [VIF_TYPE_STATS] = {
1801 : .drv_add = eth_drv_add,
1802 : .drv_delete = eth_drv_del,
1803 : },
1804 : [VIF_TYPE_MONITORING] = {
1805 : .drv_add = vhost_drv_add,
1806 : .drv_delete = vhost_drv_del,
1807 : },
1808 : };
1809 :
1810 :
1811 : unsigned int
1812 61 : vif_get_mtu(struct vr_interface *vif)
1813 : {
1814 61 : return hif_ops->hif_get_mtu(vif);
1815 : }
1816 :
1817 : static void
1818 206 : vif_free(struct vr_interface *vif)
1819 : {
1820 : unsigned int i;
1821 :
1822 206 : if (!vif)
1823 0 : return;
1824 :
1825 2678 : for (i = 0; i < vr_num_cpus; i++) {
1826 2472 : if (vif->vif_stats[i].vis_queue_ierrors_to_lcore) {
1827 2472 : vr_free(vif->vif_stats[i].vis_queue_ierrors_to_lcore,
1828 : VR_INTERFACE_TO_LCORE_ERRORS_OBJECT);
1829 : }
1830 : }
1831 :
1832 206 : if (vif->vif_stats)
1833 206 : vr_free(vif->vif_stats, VR_INTERFACE_STATS_OBJECT);
1834 :
1835 206 : if (vif->vif_vrf_table) {
1836 0 : vr_free(vif->vif_vrf_table, VR_INTERFACE_VRF_TABLE_OBJECT);
1837 0 : vif->vif_vrf_table = NULL;
1838 : }
1839 :
1840 206 : if (vif->vif_sub_interfaces) {
1841 0 : vr_free(vif->vif_sub_interfaces, VR_INTERFACE_OBJECT);
1842 0 : vif->vif_sub_interfaces = NULL;
1843 : }
1844 :
1845 206 : if (vif->vif_btable) {
1846 0 : vif_bridge_deinit(vif);
1847 : }
1848 :
1849 206 : if (vif->vif_bridge_table_lock) {
1850 0 : vr_free(vif->vif_bridge_table_lock,
1851 : VR_INTERFACE_BRIDGE_LOCK_OBJECT);
1852 0 : vif->vif_bridge_table_lock = NULL;
1853 : }
1854 :
1855 206 : if (vif->vif_hw_queues) {
1856 0 : vr_free(vif->vif_hw_queues, VR_INTERFACE_QUEUE_OBJECT);
1857 0 : vif->vif_hw_queues = NULL;
1858 0 : vif->vif_num_hw_queues = 0;
1859 : }
1860 :
1861 206 : if (vif->vif_src_mac) {
1862 0 : vr_free(vif->vif_src_mac, VR_INTERFACE_MAC_OBJECT);
1863 0 : vif->vif_src_mac = NULL;
1864 : }
1865 :
1866 1030 : for (i = 0; i < VIF_FAT_FLOW_MAXPROTO_INDEX; i++) {
1867 824 : if (vif->vif_fat_flow_no_prefix_rules[i]) {
1868 0 : vif_fat_flow_free(vif->vif_fat_flow_no_prefix_rules[i]);
1869 0 : vif->vif_fat_flow_no_prefix_rules[i] = NULL;
1870 : }
1871 : }
1872 206 : if (vif->vif_fat_flow_v4_src_prefix_rules) {
1873 0 : vdata_mtrie_delete_all(vif->vif_fat_flow_v4_src_prefix_rules);
1874 : }
1875 206 : if (vif->vif_fat_flow_v4_dst_prefix_rules) {
1876 0 : vdata_mtrie_delete_all(vif->vif_fat_flow_v4_dst_prefix_rules);
1877 : }
1878 206 : if (vif->vif_fat_flow_v6_src_prefix_rules) {
1879 0 : vdata_mtrie_delete_all(vif->vif_fat_flow_v6_src_prefix_rules);
1880 : }
1881 206 : if (vif->vif_fat_flow_v6_dst_prefix_rules) {
1882 0 : vdata_mtrie_delete_all(vif->vif_fat_flow_v6_dst_prefix_rules);
1883 : }
1884 206 : if (vif->vif_fat_flow_rule_data_list) {
1885 0 : __vif_fat_flow_free_all_rule_data_list(vif->vif_fat_flow_rule_data_list);
1886 : }
1887 206 : if (vif->fat_flow_cfg) {
1888 0 : vr_free(vif->fat_flow_cfg, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
1889 : }
1890 :
1891 206 : if (vif->vif_in_mirror_md) {
1892 0 : vif->vif_in_mirror_md_len = 0;
1893 0 : vif->vif_in_mirror_md_size = 0;
1894 0 : vr_free(vif->vif_in_mirror_md, VR_INTERFACE_MIRROR_META_OBJECT);
1895 0 : vif->vif_in_mirror_md = NULL;
1896 : }
1897 :
1898 206 : if (vif->vif_out_mirror_md) {
1899 0 : vif->vif_out_mirror_md_len = 0;
1900 0 : vif->vif_out_mirror_md_size = 0;
1901 0 : vr_free(vif->vif_out_mirror_md, VR_INTERFACE_MIRROR_META_OBJECT);
1902 0 : vif->vif_out_mirror_md = NULL;
1903 : }
1904 :
1905 206 : if (vif->vif_drop_stats) {
1906 206 : vr_free(vif->vif_drop_stats, VR_DROP_STATS_OBJECT);
1907 206 : vif->vif_drop_stats = NULL;
1908 : }
1909 :
1910 206 : if (vif->vif_pcpu_drop_stats) {
1911 206 : vr_btable_free(vif->vif_pcpu_drop_stats);
1912 206 : vif->vif_pcpu_drop_stats = NULL;
1913 : }
1914 :
1915 206 : vr_free(vif, VR_INTERFACE_OBJECT);
1916 :
1917 206 : return;
1918 : }
1919 :
1920 : void
1921 1898 : vrouter_put_interface(struct vr_interface *vif)
1922 : {
1923 1898 : if (!vr_sync_sub_and_fetch_32u(&vif->vif_users, 1))
1924 206 : vif_free(vif);
1925 :
1926 1898 : return;
1927 : }
1928 :
1929 : struct vr_interface *
1930 225459 : __vrouter_get_interface(struct vrouter *router, unsigned int idx)
1931 : {
1932 225459 : if (!router || idx >= router->vr_max_interfaces)
1933 5 : return NULL;
1934 :
1935 225454 : return router->vr_interfaces[idx];
1936 : }
1937 :
1938 0 : struct vr_interface *vrouter_get_vhost_interface(struct vrouter *router)
1939 : {
1940 : struct vr_interface *vif;
1941 :
1942 0 : vif = router->vr_host_if;
1943 0 : if (vif && vif_is_vhost(vif)) {
1944 0 : return vif;
1945 : }
1946 :
1947 0 : return NULL;
1948 :
1949 : }
1950 : struct vr_interface *
1951 0 : __vrouter_get_interface_os(struct vrouter *router, unsigned int os_idx)
1952 : {
1953 : unsigned int i;
1954 : struct vr_interface *vif;
1955 :
1956 0 : for (i = 0; i < router->vr_max_interfaces; i++) {
1957 0 : vif = __vrouter_get_interface(router, i);
1958 0 : if (vif && vif->vif_os_idx == os_idx)
1959 0 : return vif;
1960 : }
1961 :
1962 0 : return NULL;
1963 : }
1964 :
1965 :
1966 : struct vr_interface *
1967 2329 : vrouter_get_interface(unsigned int rid, unsigned int idx)
1968 : {
1969 : struct vr_interface *vif;
1970 2329 : struct vrouter *router = vrouter_get(rid);
1971 :
1972 2329 : vif = __vrouter_get_interface(router, idx);
1973 2329 : if (vif)
1974 2317 : (void)vr_sync_add_and_fetch_32u(&vif->vif_users, 1);
1975 :
1976 2329 : return vif;
1977 : }
1978 :
1979 : static void
1980 332 : vrouter_del_interface(struct vr_interface *vif)
1981 : {
1982 : struct vrouter *router;
1983 : int i;
1984 :
1985 332 : if (!vif || !(router = vrouter_get(vif->vif_rid)))
1986 0 : return;
1987 :
1988 332 : if (vif->vif_idx >= router->vr_max_interfaces)
1989 0 : return;
1990 :
1991 332 : if (router->vr_interfaces[vif->vif_idx] != vif)
1992 0 : return;
1993 :
1994 332 : router->vr_interfaces[vif->vif_idx] = NULL;
1995 :
1996 332 : switch (vif->vif_type) {
1997 42 : case VIF_TYPE_AGENT:
1998 42 : router->vr_agent_if = NULL;
1999 42 : agent_alive = false;
2000 42 : break;
2001 :
2002 50 : case VIF_TYPE_HOST:
2003 50 : router->vr_host_if = NULL;
2004 200 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2005 150 : if (vif->vif_bridge[i]) {
2006 10 : vif->vif_bridge[i]->vif_bridge[0] = NULL;
2007 10 : vif->vif_bridge[i] = NULL;
2008 : }
2009 : }
2010 :
2011 50 : break;
2012 :
2013 72 : case VIF_TYPE_PHYSICAL:
2014 72 : if (vif->vif_bridge[0]) {
2015 48 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2016 48 : if (vif->vif_bridge[0]->vif_bridge[i] == vif) {
2017 48 : vif->vif_bridge[0]->vif_bridge[i] = NULL;
2018 48 : break;
2019 : }
2020 : }
2021 48 : vif->vif_bridge[0] = NULL;
2022 : }
2023 :
2024 288 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2025 216 : if (router->vr_eth_if[i] == vif)
2026 48 : router->vr_eth_if[i] = NULL;
2027 : }
2028 72 : router->vr_num_phy_interfaces--;
2029 72 : router->vr_l3mh_intf_bitpos &= ~(1 << vif->vif_idx);
2030 72 : break;
2031 :
2032 168 : case VIF_TYPE_VIRTUAL:
2033 168 : break;
2034 :
2035 0 : default:
2036 0 : break;
2037 : }
2038 :
2039 332 : if (!vr_not_ready)
2040 329 : vr_delay_op();
2041 :
2042 332 : vrouter_put_interface(vif);
2043 :
2044 332 : return;
2045 : }
2046 :
2047 : static void
2048 332 : vrouter_setup_vif(struct vr_interface *vif)
2049 : {
2050 : int i;
2051 332 : switch (vif->vif_type) {
2052 42 : case VIF_TYPE_AGENT:
2053 42 : agent_alive = true;
2054 42 : vhost_remove_xconnect();
2055 42 : break;
2056 :
2057 50 : case VIF_TYPE_HOST:
2058 50 : if (!agent_alive) {
2059 49 : vif_set_xconnect(vif);
2060 196 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2061 147 : if (vif->vif_bridge[i])
2062 49 : vif_set_xconnect(vif->vif_bridge[i]);
2063 : }
2064 : } else {
2065 1 : vif_remove_xconnect(vif);
2066 4 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2067 3 : if (vif->vif_bridge[i])
2068 1 : vif_remove_xconnect(vif->vif_bridge[i]);
2069 : }
2070 : }
2071 :
2072 50 : break;
2073 :
2074 240 : default:
2075 240 : break;
2076 : }
2077 :
2078 332 : return;
2079 : }
2080 :
2081 : /*
2082 : * rewrite information is needed in cases where the packets are sent out
2083 : * on cases other than from nexthops. one instance where having a rewrite
2084 : * helps is for packets that are trapped to the agent from datapath.
2085 : */
2086 : static void
2087 332 : vrouter_set_rewrite(struct vr_interface *vif)
2088 : {
2089 : unsigned char *ptr;
2090 :
2091 332 : ptr = vif->vif_rewrite;
2092 : /*
2093 : * the DMAC would already have been set as part of
2094 : * driver add
2095 : */
2096 332 : ptr += VR_ETHER_ALEN;
2097 332 : memcpy(ptr, vif->vif_mac, VR_ETHER_ALEN);
2098 332 : ptr += VR_ETHER_ALEN;
2099 332 : *(unsigned short *)ptr = htons(VR_ETH_PROTO_IP);
2100 :
2101 332 : return;
2102 : }
2103 :
2104 : /*
2105 : * add the interface to the vrouter. essentially, we init the
2106 : * reference count
2107 : */
2108 : static int
2109 332 : vrouter_add_interface(struct vr_interface *vif, vr_interface_req *vifr)
2110 : {
2111 332 : struct vrouter *router = vrouter_get(vif->vif_rid);
2112 332 : struct vr_interface *eth_vif[VR_MAX_PHY_INF] = {NULL};
2113 : int i;
2114 :
2115 332 : if (!router) {
2116 0 : return -ENODEV;
2117 : }
2118 332 : if (router->vr_interfaces[vif->vif_idx])
2119 0 : return -EEXIST;
2120 :
2121 332 : if (vif->vif_type == VIF_TYPE_HOST) {
2122 50 : if (router->vr_num_phy_interfaces == 0) {
2123 0 : vr_printf("%s: Num of phy interfaces is 0 \n",
2124 : __func__);
2125 0 : return -ENODEV;
2126 : }
2127 110 : for (i = 0; i < router->vr_num_phy_interfaces; i++) {
2128 : #ifdef PLATFORM_IS_DPDK
2129 60 : eth_vif[i] = __vrouter_get_interface(router, i);
2130 : #else
2131 : if ((!vifr->vifr_cross_connect_idx) ||
2132 : (vifr->vifr_cross_connect_idx[i] < 0)) {
2133 : vr_printf("Vrouter: %s:%d vifr_idx: %d vifr_cross_connect_idx=%d\n",
2134 : __func__, __LINE__, vifr->vifr_idx,
2135 : vifr->vifr_cross_connect_idx? vifr->vifr_cross_connect_idx[i]: 0);
2136 : return -EINVAL;
2137 : }
2138 : eth_vif[i] = __vrouter_get_interface_os(router,
2139 : vifr->vifr_cross_connect_idx[i]);
2140 : #endif
2141 60 : if(!eth_vif[i]) {
2142 0 : vr_printf("%s vifr_cross_connect_idx eth_vif[%d]is NULL\n",
2143 : __func__, i);
2144 0 : return -ENODEV;
2145 : }
2146 : }
2147 : }
2148 :
2149 332 : vif->vif_router = router;
2150 332 : vif->vif_users++;
2151 332 : vif->vif_gen = vrouter_generation_num_get(router);
2152 332 : router->vr_interfaces[vif->vif_idx] = vif;
2153 :
2154 332 : switch (vif->vif_type) {
2155 42 : case VIF_TYPE_AGENT:
2156 42 : router->vr_agent_if = vif;
2157 42 : break;
2158 :
2159 50 : case VIF_TYPE_HOST:
2160 50 : if (!strncmp(vif->vif_name, "vhost0", 5)) {
2161 45 : router->vr_host_if = vif;
2162 180 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2163 135 : if (eth_vif[i]) {
2164 50 : router->vr_eth_if[i] = eth_vif[i];
2165 50 : vif->vif_bridge[i] = eth_vif[i];
2166 : /*
2167 : * Condition to ensure the following assignment of bridge
2168 : * happens for all cases except for dpdk in l3mh mode. In
2169 : * the case of dpdk in l3mh mode, the dpdk_if_add_tun_tap()
2170 : * function assigns the bridge.
2171 : */
2172 : #ifdef PLATFORM_IS_DPDK
2173 50 : if(!is_vrouter_multihomed(router))
2174 40 : eth_vif[i]->vif_bridge[0] = vif;
2175 : #else
2176 : eth_vif[i]->vif_bridge[0] = vif;
2177 : #endif
2178 : }
2179 : }
2180 : }
2181 50 : break;
2182 :
2183 72 : case VIF_TYPE_PHYSICAL:
2184 72 : router->vr_num_phy_interfaces++;
2185 72 : router->vr_l3mh_intf_bitpos |= (1 << vif->vif_idx);
2186 72 : vr_printf("Num phy interfaces %d\n", router->vr_num_phy_interfaces);
2187 72 : break;
2188 :
2189 168 : default:
2190 168 : break;
2191 : }
2192 :
2193 332 : vrouter_set_rewrite(vif);
2194 :
2195 332 : return 0;
2196 : }
2197 :
2198 : void
2199 0 : vif_attach(struct vr_interface *vif)
2200 : {
2201 0 : if (vif_drivers[vif->vif_type].drv_add)
2202 0 : vif_drivers[vif->vif_type].drv_add(vif, NULL);
2203 :
2204 0 : return;
2205 : }
2206 :
2207 : void
2208 0 : vif_detach(struct vr_interface *vif)
2209 : {
2210 0 : if (vif_drivers[vif->vif_type].drv_delete)
2211 0 : vif_drivers[vif->vif_type].drv_delete(vif);
2212 :
2213 0 : return;
2214 : }
2215 :
2216 : static void
2217 332 : vif_drv_delete(struct vr_interface *vif)
2218 : {
2219 332 : if (hif_ops->hif_lock)
2220 332 : hif_ops->hif_lock();
2221 :
2222 : /*
2223 : * setting name to NULL is important in preventing races. Races mainly
2224 : * come from interfaces going away/coming back (from OS. mainly virtual
2225 : * interfaces such as vlan, tap, bond etc.) and agent simultaneously
2226 : * trying to add/delete vif. vif_find will be used by the OS specific
2227 : * code when an interface goes away/comes back to find the vif corresponding
2228 : * to the name. Setting name to NULL partially makes sure that vif is
2229 : * not found in delete cases. the other safety we have is in the rtnl_lock.
2230 : * the hos_if_* (add/del/tap) does some jugglery (which involves, checking
2231 : * for name) under rtnl_lock to make sure that states are proper.
2232 : */
2233 332 : vif->vif_name[0] = '\0';
2234 332 : if (vif_drivers[vif->vif_type].drv_delete)
2235 332 : vif_drivers[vif->vif_type].drv_delete(vif);
2236 :
2237 : /*
2238 : * the check is right. If you haven't defined unlock, you deserve the
2239 : * crash
2240 : */
2241 332 : if (hif_ops->hif_lock)
2242 332 : hif_ops->hif_unlock();
2243 :
2244 332 : return;
2245 : }
2246 :
2247 : int
2248 329 : vif_delete(struct vr_interface *vif)
2249 : {
2250 329 : vif_drv_delete(vif);
2251 329 : vrouter_del_interface(vif);
2252 329 : return 0;
2253 : }
2254 :
2255 : struct vr_interface *
2256 335 : vif_find(struct vrouter *router, char *name)
2257 : {
2258 : int i;
2259 : struct vr_interface *vif;
2260 :
2261 44988 : for (i = 0; i < router->vr_max_interfaces; i++) {
2262 44978 : vif = router->vr_interfaces[i];
2263 44978 : if (vif && !strncmp(vif->vif_name, name, sizeof(vif->vif_name)))
2264 325 : return vif;
2265 : }
2266 :
2267 10 : return NULL;
2268 : }
2269 :
2270 : static int
2271 332 : vif_drv_add(struct vr_interface *vif, vr_interface_req *req)
2272 : {
2273 332 : int ret = 0;
2274 :
2275 332 : if (vif_drivers[vif->vif_type].drv_add) {
2276 332 : if (hif_ops->hif_lock)
2277 332 : hif_ops->hif_lock();
2278 :
2279 332 : ret = vif_drivers[vif->vif_type].drv_add(vif, req);
2280 :
2281 : /*
2282 : * the check is right. If you haven't defined unlock, you deserve the
2283 : * crash
2284 : */
2285 332 : if (hif_ops->hif_lock)
2286 332 : hif_ops->hif_unlock();
2287 :
2288 332 : if (ret)
2289 0 : return ret;
2290 : }
2291 :
2292 332 : vif->vif_driver = &vif_drivers[vif->vif_type];
2293 332 : return 0;
2294 :
2295 : }
2296 :
2297 : static int
2298 343 : vr_interface_delete(vr_interface_req *req, bool need_response)
2299 : {
2300 343 : int ret = 0;
2301 : struct vr_interface *vif;
2302 343 : struct vrouter *router = vrouter_get(req->vifr_rid);
2303 :
2304 : /* Interface can be deleted using vif name of OS interface name or
2305 : * index
2306 : */
2307 343 : if (req->vifr_name) {
2308 335 : if (2 == sscanf(req->vifr_name, "vif%u/%u", &req->vifr_rid,
2309 : &req->vifr_idx))
2310 0 : vif = __vrouter_get_interface(vrouter_get(req->vifr_rid),
2311 0 : req->vifr_idx);
2312 : else
2313 335 : vif = vif_find(router, req->vifr_name);
2314 : } else {
2315 8 : vif = __vrouter_get_interface(router, req->vifr_idx);
2316 : }
2317 :
2318 343 : if (!vif && (ret = -ENODEV))
2319 14 : goto del_fail;
2320 :
2321 329 : vr_offload_interface_del(vif);
2322 :
2323 329 : vif_delete(vif);
2324 :
2325 343 : del_fail:
2326 343 : if (need_response)
2327 343 : vr_send_response(ret);
2328 :
2329 343 : return ret;
2330 : }
2331 :
2332 : static void
2333 0 : vif_free_bridge_table_lock(struct vrouter *router, void *data)
2334 : {
2335 0 : struct vr_defer_data *vdd = (struct vr_defer_data *)data;
2336 :
2337 0 : if (!vdd)
2338 0 : return;
2339 :
2340 0 : vr_free(vdd->vdd_data, VR_INTERFACE_BRIDGE_LOCK_OBJECT);
2341 :
2342 0 : return;
2343 : }
2344 :
2345 : static int
2346 349 : vif_set_flags(struct vr_interface *vif, vr_interface_req *req)
2347 : {
2348 : void *mem;
2349 : struct vr_defer_data *vdd;
2350 :
2351 349 : if ((req->vifr_flags & VIF_FLAG_MAC_LEARN) || (vif_is_fabric(vif))) {
2352 72 : if (!vif->vif_bridge_table_lock) {
2353 72 : vif->vif_bridge_table_lock =
2354 72 : vr_zalloc(vr_num_cpus * sizeof(uint8_t),
2355 : VR_INTERFACE_BRIDGE_LOCK_OBJECT);
2356 72 : if (!vif->vif_bridge_table_lock) {
2357 0 : return -ENOMEM;
2358 : }
2359 : }
2360 277 : } else if (vif->vif_flags & VIF_FLAG_MAC_LEARN) {
2361 0 : if (vif->vif_bridge_table_lock) {
2362 0 : vdd = vr_get_defer_data(sizeof(*vdd));
2363 0 : if (vdd) {
2364 0 : mem = vif->vif_bridge_table_lock;
2365 0 : vif->vif_bridge_table_lock = NULL;
2366 0 : vdd->vdd_data = mem;
2367 0 : vr_defer(vif->vif_router, vif_free_bridge_table_lock,
2368 : (void *)vdd);
2369 : }
2370 : }
2371 : }
2372 :
2373 349 : vif->vif_flags = (vif->vif_flags & VIF_VR_CAP_MASK) |
2374 349 : (req->vifr_flags & ~VIF_VR_CAP_MASK);
2375 :
2376 : /*
2377 : * If both L3 and L2 are disabled, enabled L3 with fallback bridging
2378 : * by default to avoid total blackout of packets
2379 : */
2380 349 : if (!(vif->vif_flags & (VIF_FLAG_L3_ENABLED | VIF_FLAG_L2_ENABLED))) {
2381 254 : vif->vif_flags |= (VIF_FLAG_L3_ENABLED | VIF_FLAG_L2_ENABLED);
2382 : }
2383 :
2384 349 : return 0;
2385 : }
2386 :
2387 : static int
2388 349 : vr_interface_mirror_md_set(struct vr_interface *vif, vr_interface_req *req)
2389 : {
2390 : /*
2391 : * If metadata is removed from request, make our metadata len to
2392 : * zero, so that it does not get used in packet processeing. The
2393 : * memory will get freed only at the time of deletion of interface
2394 : * _size hold the allocated memory size, so that we would not over
2395 : * shoot while copying.
2396 : * It is also assumed that the interface metadata does not change
2397 : * once allocated
2398 : */
2399 349 : if (!req->vifr_in_mirror_md_size)
2400 349 : vif->vif_in_mirror_md_len = 0;
2401 :
2402 349 : if (!req->vifr_out_mirror_md_size)
2403 349 : vif->vif_out_mirror_md_len = 0;
2404 :
2405 349 : if (req->vifr_in_mirror_md_size) {
2406 0 : if (!vif->vif_in_mirror_md) {
2407 : /*
2408 : * If there is no mirror md already, ensure we dont create
2409 : * more than the max size
2410 : */
2411 0 : if (req->vifr_in_mirror_md_size > VIF_MAX_MIRROR_MD_SIZE)
2412 0 : req->vifr_in_mirror_md_size = VIF_MAX_MIRROR_MD_SIZE;
2413 :
2414 0 : vif->vif_in_mirror_md =
2415 0 : vr_zalloc(req->vifr_in_mirror_md_size,
2416 : VR_INTERFACE_MIRROR_META_OBJECT);
2417 0 : if (!vif->vif_in_mirror_md)
2418 0 : return -ENOMEM;
2419 :
2420 0 : vif->vif_in_mirror_md_size = req->vifr_in_mirror_md_size;
2421 : } else {
2422 : /*
2423 : * If mirror md already exists, we dont want the new len to
2424 : * be more than that
2425 : */
2426 0 : if (req->vifr_in_mirror_md_size > vif->vif_in_mirror_md_size) {
2427 0 : req->vifr_in_mirror_md_size = vif->vif_in_mirror_md_size;
2428 : }
2429 : }
2430 :
2431 0 : memcpy(vif->vif_in_mirror_md,
2432 0 : req->vifr_in_mirror_md, req->vifr_in_mirror_md_size);
2433 0 : vif->vif_in_mirror_md_len = req->vifr_in_mirror_md_size;
2434 : }
2435 :
2436 349 : if (req->vifr_out_mirror_md_size) {
2437 0 : if (!vif->vif_out_mirror_md) {
2438 0 : if (req->vifr_out_mirror_md_size > VIF_MAX_MIRROR_MD_SIZE)
2439 0 : req->vifr_out_mirror_md_size = VIF_MAX_MIRROR_MD_SIZE;
2440 :
2441 0 : vif->vif_out_mirror_md =
2442 0 : vr_zalloc(req->vifr_out_mirror_md_size,
2443 : VR_INTERFACE_MIRROR_META_OBJECT);
2444 0 : if (!vif->vif_out_mirror_md)
2445 0 : return -ENOMEM;
2446 :
2447 0 : vif->vif_out_mirror_md_size = req->vifr_out_mirror_md_size;
2448 : } else {
2449 0 : if (req->vifr_out_mirror_md_size > vif->vif_out_mirror_md_size) {
2450 0 : req->vifr_out_mirror_md_size = vif->vif_out_mirror_md_size;
2451 : }
2452 : }
2453 :
2454 0 : memcpy(vif->vif_out_mirror_md,
2455 0 : req->vifr_out_mirror_md, req->vifr_out_mirror_md_size);
2456 0 : vif->vif_out_mirror_md_len = req->vifr_out_mirror_md_size;
2457 : }
2458 :
2459 349 : return 0;
2460 : }
2461 :
2462 : static int
2463 17 : vr_interface_change(struct vr_interface *vif, vr_interface_req *req)
2464 : {
2465 17 : int ret = 0;
2466 : uint64_t *ip6;
2467 :
2468 17 : if (req->vifr_flags & VIF_FLAG_SERVICE_IF &&
2469 0 : !(vif->vif_flags & VIF_FLAG_SERVICE_IF)) {
2470 0 : ret = vr_interface_service_enable(vif);
2471 0 : if (ret)
2472 0 : return ret;
2473 17 : } else if ((vif->vif_flags & VIF_FLAG_SERVICE_IF) &&
2474 0 : !(req->vifr_flags & VIF_FLAG_SERVICE_IF)) {
2475 0 : vr_interface_service_disable(vif);
2476 : }
2477 :
2478 17 : ret = vif_set_flags(vif, req);
2479 17 : if (ret)
2480 0 : return ret;
2481 :
2482 17 : vif->vif_mirror_id = req->vifr_mir_id;
2483 17 : if (!(vif->vif_flags & VIF_FLAG_MIRROR_RX) &&
2484 17 : !(vif->vif_flags & VIF_FLAG_MIRROR_TX)) {
2485 17 : vif->vif_mirror_id = VR_MAX_MIRROR_INDICES;
2486 : }
2487 17 : if (req->vifr_vrf >= 0)
2488 17 : vif->vif_vrf = req->vifr_vrf;
2489 :
2490 17 : if (req->vifr_mcast_vrf >= 0)
2491 17 : vif->vif_mcast_vrf = req->vifr_mcast_vrf;
2492 :
2493 17 : if (req->vifr_mtu)
2494 17 : vif->vif_mtu = req->vifr_mtu;
2495 :
2496 17 : vif->vif_nh_id = req->vifr_nh_id;
2497 17 : vif->vif_qos_map_index = req->vifr_qos_map_index;
2498 17 : vif->vif_isid = req->vifr_isid;
2499 17 : if (req->vifr_pbb_mac_size)
2500 0 : VR_MAC_COPY(vif->vif_pbb_mac, req->vifr_pbb_mac);
2501 :
2502 17 : vif->vif_ip = req->vifr_ip;
2503 17 : ip6 = (uint64_t *)(vif->vif_ip6);
2504 17 : *ip6 = req->vifr_ip6_u;
2505 17 : *(ip6 + 1) = req->vifr_ip6_l;
2506 :
2507 17 : ret = vr_interface_mirror_md_set(vif, req);
2508 17 : if (ret)
2509 0 : return ret;
2510 :
2511 17 : if ((ret = vif_fat_flow_add(vif, req)))
2512 0 : return ret;
2513 :
2514 17 : return vlan_sub_interface_manage(vif->vif_parent, vif,
2515 17 : req->vifr_src_mac_size / VR_ETHER_ALEN, req->vifr_src_mac);
2516 :
2517 : }
2518 :
2519 : static bool
2520 349 : vif_transport_valid(vr_interface_req *req)
2521 : {
2522 349 : switch (req->vifr_transport) {
2523 349 : case VIF_TRANSPORT_VIRTUAL:
2524 : case VIF_TRANSPORT_ETH:
2525 : case VIF_TRANSPORT_PMD:
2526 : case VIF_TRANSPORT_SOCKET:
2527 349 : return true;
2528 :
2529 0 : default:
2530 0 : break;
2531 : }
2532 :
2533 0 : return false;
2534 : }
2535 :
2536 : int
2537 349 : vr_interface_add(vr_interface_req *req, bool need_response)
2538 : {
2539 349 : int i, ret = 0;
2540 : uint64_t *ip6;
2541 349 : struct vr_interface *vif = NULL, *eth_vif = NULL;
2542 349 : struct vrouter *router = vrouter_get(req->vifr_rid);
2543 :
2544 349 : if (!router || ((unsigned int)req->vifr_idx >= router->vr_max_interfaces)) {
2545 0 : vr_printf("Vrouter: %s:%d vifr_idx: %d vifr_type:%d vr_max_intf : %u \n",
2546 : __func__, __LINE__, req->vifr_idx, req->vifr_type, router->vr_max_interfaces);
2547 0 : ret = -EINVAL;
2548 0 : goto error;
2549 : }
2550 :
2551 349 : if (req->vifr_type >= VIF_TYPE_MAX && (ret = -EINVAL)) {
2552 0 : vr_printf("Vrouter: %s:%d vifr_transport:%d vifr_name:%s vifr_idx:%d\n",
2553 0 : __func__, __LINE__, req->vifr_transport, req->vifr_name, req->vifr_idx);
2554 0 : goto error;
2555 : }
2556 :
2557 349 : if (!vif_transport_valid(req))
2558 0 : goto error;
2559 :
2560 349 : vif = __vrouter_get_interface(router, req->vifr_idx);
2561 349 : if (vif) {
2562 :
2563 17 : if (vif_is_vhost(vif) && (!strncmp(req->vifr_name, "vhost0", 5))) {
2564 0 : vr_printf("%s: vhost interface change \n", __FUNCTION__);
2565 :
2566 0 : if (is_vrouter_multihomed(router)) {
2567 :
2568 0 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2569 0 : if(router->vr_eth_if[i]) {
2570 0 : if (hif_ops->hif_lock)
2571 0 : hif_ops->hif_lock();
2572 :
2573 : #ifdef PLATFORM_IS_DPDK
2574 0 : ret = hif_ops->hif_add_tun_tap(
2575 : __vrouter_get_interface(router, i), req);
2576 : #endif
2577 :
2578 0 : if (hif_ops->hif_lock)
2579 0 : hif_ops->hif_unlock();
2580 : #ifdef PLATFORM_IS_DPDK
2581 0 : if(ret) {
2582 0 : ret = hif_ops->hif_del_tun_tap(__vrouter_get_interface(
2583 0 : router, VR_TOTAL_INTERFACES + i));
2584 : }
2585 : #else
2586 : /*
2587 : * eth_bridge is not assigned to vhost0 in
2588 : * case of l3mh in dpdk mode
2589 : */
2590 : eth_vif = __vrouter_get_interface(router, i);
2591 : if (eth_vif) {
2592 : vr_printf("%s Setting vif->vif_bridge for vif %d\n",
2593 : __func__, eth_vif->vif_idx);
2594 : eth_vif->vif_bridge[0] = vif;
2595 : }
2596 : #endif
2597 : }
2598 : }
2599 : }
2600 : }
2601 :
2602 17 : ret = vr_interface_change(vif, req);
2603 : /* notify hw offload of change, if enabled */
2604 17 : if (!ret)
2605 17 : ret = vr_offload_interface_add(vif);
2606 :
2607 17 : goto generate_resp;
2608 : }
2609 :
2610 332 : vif = vr_zalloc(sizeof(*vif), VR_INTERFACE_OBJECT);
2611 332 : if (!vif) {
2612 0 : ret = -ENOMEM;
2613 0 : goto error;
2614 : }
2615 :
2616 332 : vif->vif_stats = vr_zalloc(vr_num_cpus *
2617 : sizeof(struct vr_interface_stats), VR_INTERFACE_STATS_OBJECT);
2618 332 : if (!vif->vif_stats) {
2619 0 : ret = -ENOMEM;
2620 0 : goto error;
2621 : }
2622 :
2623 4316 : for (i = 0; i < vr_num_cpus; i++) {
2624 3984 : vif->vif_stats[i].vis_queue_ierrors_to_lcore = vr_zalloc(vr_num_cpus *
2625 : sizeof(uint64_t), VR_INTERFACE_TO_LCORE_ERRORS_OBJECT);
2626 3984 : if (!vif->vif_stats[i].vis_queue_ierrors_to_lcore) {
2627 0 : ret = -ENOMEM;
2628 0 : goto error;
2629 : }
2630 : }
2631 :
2632 : /*
2633 : * The dropstats need to be available per interface. Incrementing
2634 : * atomically the same statistics across many CPUs might attract
2635 : * significatnt delay. Alternative approach of allocating memory for
2636 : * every dropstat for every CPU will be large chunk of memory
2637 : * considering large number of interfaces, number of dropstats,
2638 : * number of CPUs and size of every counter. To normalise both the
2639 : * requirements, one set of dropstats of 64 bit size and another set
2640 : * of dropstats of one byte per every cpu is allocated. The later is
2641 : * incremented without any contention as it is per cpu. When the
2642 : * one byte counter reaches its max value, it is added to the
2643 : * 64 bit counter atomically. This results in decreasing the delay
2644 : * as well decresing the memory requirement
2645 : */
2646 332 : vif->vif_drop_stats = vr_zalloc((VP_DROP_MAX * sizeof(uint64_t)),
2647 : VR_DROP_STATS_OBJECT);
2648 332 : if (!vif->vif_drop_stats) {
2649 0 : ret = -ENOMEM;
2650 0 : goto error;
2651 : }
2652 :
2653 : /*
2654 : * We continue to create the interface even if per cpu stats
2655 : * allocation fails. In this case, we directly increment on
2656 : * vif_drop_stats atomically
2657 : */
2658 332 : vif->vif_pcpu_drop_stats = vr_btable_alloc((vr_num_cpus * VP_DROP_MAX), 1);
2659 :
2660 332 : vif->vif_type = req->vifr_type;
2661 :
2662 332 : ret = vif_set_flags(vif, req);
2663 332 : if (ret)
2664 0 : goto error;
2665 :
2666 332 : vif->vif_vrf = req->vifr_vrf;
2667 332 : vif->vif_mcast_vrf = req->vifr_mcast_vrf;
2668 332 : vif->vif_vlan_id = VLAN_ID_INVALID;
2669 332 : vif->vif_mtu = req->vifr_mtu;
2670 332 : vif->vif_idx = req->vifr_idx;
2671 332 : vif->vif_transport = req->vifr_transport;
2672 332 : vif->vif_os_idx = req->vifr_os_idx;
2673 332 : vif->vif_vhostuser_mode = req->vifr_vhostuser_mode;
2674 332 : if (req->vifr_os_idx == -1)
2675 0 : vif->vif_os_idx = 0;
2676 332 : vif->vif_rid = req->vifr_rid;
2677 332 : vif->vif_nh_id = req->vifr_nh_id;
2678 332 : vif->vif_qos_map_index = req->vifr_qos_map_index;
2679 332 : vif->vif_isid = req->vifr_isid;
2680 332 : if (req->vifr_pbb_mac_size)
2681 0 : VR_MAC_COPY(vif->vif_pbb_mac, req->vifr_pbb_mac);
2682 :
2683 332 : vif->vif_mirror_id = req->vifr_mir_id;
2684 332 : if (!(vif->vif_flags & VIF_FLAG_MIRROR_RX) &&
2685 332 : !(vif->vif_flags & VIF_FLAG_MIRROR_TX)) {
2686 331 : vif->vif_mirror_id = VR_MAX_MIRROR_INDICES;
2687 : }
2688 332 : ret = vr_interface_mirror_md_set(vif, req);
2689 332 : if (ret)
2690 0 : goto error;
2691 :
2692 332 : if (req->vifr_mac) {
2693 332 : if (req->vifr_mac_size != sizeof(vif->vif_mac)) {
2694 0 : vr_printf("Vrouter: %s:%d Incorrect mac size %d\n", __func__, __LINE__, req->vifr_mac_size);
2695 0 : ret = -EINVAL;
2696 0 : goto error;
2697 : }
2698 :
2699 332 : memcpy(vif->vif_mac, req->vifr_mac, sizeof(vif->vif_mac));
2700 332 : memcpy(vif->vif_rewrite, req->vifr_mac, sizeof(vif->vif_mac));
2701 : }
2702 :
2703 332 : vif->vif_ip = req->vifr_ip;
2704 332 : ip6 = (uint64_t *)(vif->vif_ip6);
2705 332 : *ip6 = req->vifr_ip6_u;
2706 332 : *(ip6 + 1) = req->vifr_ip6_l;
2707 :
2708 : /* Enable IPv6 underlay if vhost has an IPv6 address */
2709 332 : if (vif_is_vhost(vif) && ((*ip6 != 0) || ((*(ip6+1)) != 0))) {
2710 9 : vr_printf("Enabling IPv6 underlay in vRouter\n");
2711 9 : vr_set_ipv6_underlay_enabled();
2712 : }
2713 :
2714 332 : if (req->vifr_name) {
2715 332 : strncpy(vif->vif_name, req->vifr_name, sizeof(vif->vif_name) - 1);
2716 : }
2717 :
2718 332 : if (req->vifr_hw_queues_size) {
2719 0 : vif->vif_hw_queues = vr_malloc(sizeof(uint16_t) *
2720 0 : req->vifr_hw_queues_size, VR_INTERFACE_QUEUE_OBJECT);
2721 0 : if (!vif->vif_hw_queues) {
2722 0 : ret = -ENOMEM;
2723 0 : goto error;
2724 : }
2725 :
2726 0 : vif->vif_num_hw_queues = req->vifr_hw_queues_size;
2727 0 : memcpy(vif->vif_hw_queues, req->vifr_hw_queues,
2728 0 : req->vifr_hw_queues_size * sizeof(uint16_t));
2729 : }
2730 :
2731 332 : ret = vif_fat_flow_add(vif, req);
2732 332 : if (ret){
2733 0 : vr_printf("Vrouter: %s:%d ret:%d\n", __func__, __LINE__, ret);
2734 0 : goto error;
2735 : }
2736 :
2737 : /*
2738 : * the order below is probably not intuitive, but we do this because
2739 : * the moment we do a drv_add, packets will start coming in and find
2740 : * that vif_router is not set. to avoid checks such as !vif_router in
2741 : * datapath, the order has to be what is below.
2742 : */
2743 332 : vif->vif_rx = vif_discard_rx;
2744 332 : vif->vif_tx = vif_discard_tx;
2745 332 : ret = vrouter_add_interface(vif, req);
2746 332 : if (ret)
2747 0 : goto error;
2748 :
2749 332 : ret = vif_drv_add(vif, req);
2750 332 : if (ret) {
2751 0 : vif_delete(vif);
2752 0 : vif = NULL;
2753 : }
2754 : /*
2755 : * The following code snippet is used for creating the additional tun-tap
2756 : * interfaces corresponding to each physical interface in case of l3mh
2757 : * when vrouter is in dpdk mode. These tun-tap interfaces are created by
2758 : * the vrouter itself and agent has no knowledge about it. They are a means
2759 : * by which the kernel can send/recv packets to the physical interface
2760 : * since vhost0 does not correspond to any single physical interface in
2761 : * case of l3mh.
2762 : */
2763 : #ifdef PLATFORM_IS_DPDK
2764 332 : if (!ret) {
2765 332 : if (is_vrouter_multihomed(router) &&
2766 51 : (!strncmp(vif->vif_name, "vhost0", 5))) {
2767 20 : for (i = 0; i < VR_MAX_PHY_INF; i++) {
2768 15 : if(router->vr_eth_if[i]) {
2769 10 : ret = hif_ops->hif_add_tun_tap(
2770 : __vrouter_get_interface(router, i), req);
2771 : }
2772 : }
2773 : }
2774 : }
2775 : #endif
2776 332 : if (!ret) {
2777 332 : vrouter_setup_vif(vif);
2778 332 : vr_register_nic(vif, req);
2779 : }
2780 :
2781 0 : error:
2782 332 : if (ret && vif)
2783 0 : vif_free(vif);
2784 :
2785 : /* notify hw offload of change, if enabled */
2786 332 : if (!ret) {
2787 332 : ret = vr_offload_interface_add(vif);
2788 332 : if (ret) {
2789 0 : vif_delete(vif);
2790 0 : vif = NULL;
2791 : }
2792 : }
2793 332 : generate_resp:
2794 349 : if (need_response)
2795 339 : vr_send_response(ret);
2796 :
2797 349 : return ret;
2798 : }
2799 :
2800 : static void
2801 1896 : vr_interface_add_response(vr_interface_req *req,
2802 : struct vr_interface_stats *stats)
2803 : {
2804 : int i;
2805 :
2806 1896 : req->vifr_ibytes += stats->vis_ibytes;
2807 1896 : req->vifr_ipackets += stats->vis_ipackets;
2808 1896 : req->vifr_ierrors += stats->vis_ierrors;
2809 1896 : req->vifr_obytes += stats->vis_obytes;
2810 1896 : req->vifr_opackets += stats->vis_opackets;
2811 1896 : req->vifr_oerrors += stats->vis_oerrors;
2812 :
2813 1896 : req->vifr_queue_ipackets += stats->vis_queue_ipackets;
2814 24648 : for (i = 0; i < vr_num_cpus; i++)
2815 22752 : req->vifr_queue_ierrors_to_lcore[i] += stats->vis_queue_ierrors_to_lcore[i];
2816 1896 : req->vifr_queue_ierrors_to_lcore_size = vr_num_cpus;
2817 1896 : req->vifr_queue_ierrors += stats->vis_queue_ierrors;
2818 1896 : req->vifr_queue_opackets += stats->vis_queue_opackets;
2819 1896 : req->vifr_queue_oerrors += stats->vis_queue_oerrors;
2820 :
2821 1896 : req->vifr_port_ipackets += stats->vis_port_ipackets;
2822 1896 : req->vifr_port_ierrors += stats->vis_port_ierrors;
2823 1896 : req->vifr_port_isyscalls += stats->vis_port_isyscalls;
2824 1896 : req->vifr_port_inombufs += stats->vis_port_inombufs;
2825 1896 : req->vifr_port_opackets += stats->vis_port_opackets;
2826 1896 : req->vifr_port_oerrors += stats->vis_port_oerrors;
2827 1896 : req->vifr_port_osyscalls += stats->vis_port_osyscalls;
2828 :
2829 1896 : req->vifr_dev_ibytes += stats->vis_dev_ibytes;
2830 1896 : req->vifr_dev_ipackets += stats->vis_dev_ipackets;
2831 1896 : req->vifr_dev_ierrors += stats->vis_dev_ierrors;
2832 1896 : req->vifr_dev_inombufs += stats->vis_dev_inombufs;
2833 1896 : req->vifr_dev_obytes += stats->vis_dev_obytes;
2834 1896 : req->vifr_dev_opackets += stats->vis_dev_opackets;
2835 1896 : req->vifr_dev_oerrors += stats->vis_dev_oerrors;
2836 1896 : }
2837 :
2838 : static uint64_t
2839 158 : vr_interface_get_drops(struct vr_interface *vif)
2840 : {
2841 : uint8_t *count;
2842 : unsigned int cpu;
2843 : int stats_index;
2844 : uint64_t total_drops;
2845 :
2846 158 : total_drops = 0;
2847 8848 : for (stats_index = 0; stats_index < VP_DROP_MAX; stats_index++) {
2848 8690 : total_drops += vif->vif_drop_stats[stats_index];
2849 8690 : if (vif->vif_pcpu_drop_stats) {
2850 112970 : for (cpu = 0; cpu < vr_num_cpus; cpu++) {
2851 104280 : count = vr_btable_get(vif->vif_pcpu_drop_stats,
2852 104280 : ((cpu * VP_DROP_MAX) + stats_index));
2853 104280 : total_drops += *count;
2854 : }
2855 : }
2856 : }
2857 :
2858 158 : return total_drops;
2859 : }
2860 :
2861 : static int
2862 0 : vr_interface_copy_bond_info(vr_interface_req *req,
2863 : struct vr_interface_bond_info *bond_info)
2864 : {
2865 0 : unsigned int i, len, sl_name_iter = 0, sl_drv_name_iter = 0;
2866 0 : char *buffer = NULL, *buffer_drv = NULL;
2867 :
2868 0 : buffer = vr_zalloc(VR_INTERFACE_STR_BUF_LEN, VR_INTERFACE_BOND_OBJECT);
2869 0 : if (!buffer)
2870 0 : goto error_exit;
2871 0 : buffer_drv = vr_zalloc(VR_INTERFACE_STR_BUF_LEN, VR_INTERFACE_BOND_OBJECT);
2872 0 : if (!buffer_drv)
2873 0 : goto error_exit;
2874 :
2875 0 : req->vifr_num_bond_slave = bond_info->vif_num_slave;
2876 0 : req->vifr_intf_status = bond_info->vif_intf_link_status;
2877 0 : len = strlen(bond_info->vif_fab_name);
2878 0 : req->vifr_fab_name_size = (len + 1);
2879 0 : req->vifr_fab_name =
2880 0 : vr_zalloc(req->vifr_fab_name_size * sizeof(uint8_t),
2881 : VR_INTERFACE_BOND_OBJECT);
2882 0 : if(!req->vifr_fab_name)
2883 0 : goto error_exit;
2884 0 : memcpy(req->vifr_fab_name, bond_info->vif_fab_name, len);
2885 0 : len = strlen(bond_info->vif_fab_drv_name);
2886 0 : req->vifr_fab_drv_name_size = (len + 1);
2887 0 : req->vifr_fab_drv_name =
2888 0 : vr_zalloc(req->vifr_fab_drv_name_size * sizeof(uint8_t),
2889 : VR_INTERFACE_BOND_OBJECT);
2890 0 : if(!req->vifr_fab_drv_name)
2891 0 : goto error_exit;
2892 0 : memcpy(req->vifr_fab_drv_name, bond_info->vif_fab_drv_name, len);
2893 :
2894 0 : if(bond_info->vif_num_slave) {
2895 0 : for(i = 0; i < bond_info->vif_num_slave; i++) {
2896 0 : len = strlen(bond_info->vif_slave_name[i]);
2897 0 : sl_name_iter += snprintf((buffer + sl_name_iter),
2898 0 : (VR_INTERFACE_STR_BUF_LEN - sl_name_iter - 1),
2899 : "%s", bond_info->vif_slave_name[i]);
2900 0 : if(!sl_name_iter)
2901 0 : goto error_exit;
2902 : /* Concatenate with NULL terminated string because at
2903 : * utils side delimiter used as '\0' and increment
2904 : * iter by 1 */
2905 0 : sl_name_iter += 1;
2906 :
2907 0 : len = strlen(bond_info->vif_slave_drv_name[i]);
2908 0 : sl_drv_name_iter += snprintf((buffer_drv + sl_drv_name_iter),
2909 0 : (VR_INTERFACE_STR_BUF_LEN - sl_drv_name_iter - 1),
2910 : "%s", bond_info->vif_slave_drv_name[i]);
2911 0 : if(!sl_drv_name_iter)
2912 0 : goto error_exit;
2913 0 : sl_drv_name_iter += 1;
2914 : }
2915 :
2916 0 : req->vifr_bond_slave_name_size = sl_name_iter;
2917 0 : req->vifr_bond_slave_drv_name_size = sl_drv_name_iter;
2918 :
2919 0 : req->vifr_bond_slave_name =
2920 0 : vr_zalloc(req->vifr_bond_slave_name_size *
2921 : sizeof(uint8_t), VR_INTERFACE_BOND_OBJECT);
2922 0 : if(!req->vifr_bond_slave_name)
2923 0 : goto error_exit;
2924 0 : req->vifr_bond_slave_drv_name =
2925 0 : vr_zalloc(req->vifr_bond_slave_drv_name_size *
2926 : sizeof(uint8_t), VR_INTERFACE_BOND_OBJECT);
2927 0 : if(!req->vifr_bond_slave_drv_name)
2928 0 : goto error_exit;
2929 0 : memcpy(req->vifr_bond_slave_name, buffer,
2930 0 : req->vifr_bond_slave_name_size);
2931 0 : memcpy(req->vifr_bond_slave_drv_name, buffer_drv,
2932 0 : req->vifr_bond_slave_drv_name_size);
2933 : }
2934 :
2935 0 : if (buffer)
2936 0 : vr_free(buffer, VR_INTERFACE_BOND_OBJECT);
2937 0 : if (buffer_drv)
2938 0 : vr_free(buffer_drv, VR_INTERFACE_BOND_OBJECT);
2939 0 : return 0;
2940 :
2941 0 : error_exit:
2942 0 : if (buffer)
2943 0 : vr_free(buffer, VR_INTERFACE_BOND_OBJECT);
2944 0 : if (buffer_drv)
2945 0 : vr_free(buffer_drv, VR_INTERFACE_BOND_OBJECT);
2946 0 : if (req->vifr_fab_name)
2947 0 : vr_free(req->vifr_fab_name, VR_INTERFACE_BOND_OBJECT);
2948 0 : if (req->vifr_fab_drv_name)
2949 0 : vr_free(req->vifr_fab_drv_name, VR_INTERFACE_BOND_OBJECT);
2950 0 : if (req->vifr_bond_slave_name)
2951 0 : vr_free(req->vifr_bond_slave_name, VR_INTERFACE_BOND_OBJECT);
2952 0 : if (req->vifr_bond_slave_drv_name)
2953 0 : vr_free(req->vifr_bond_slave_drv_name, VR_INTERFACE_BOND_OBJECT);
2954 :
2955 0 : return -ENOMEM;
2956 : }
2957 :
2958 : static void
2959 120 : vr_vif_stats_reset(struct vr_interface_stats *stats)
2960 : {
2961 120 : memset(stats, 0, (sizeof(struct vr_interface_stats) -
2962 : sizeof(stats->vis_queue_ierrors_to_lcore)));
2963 120 : memset(stats->vis_queue_ierrors_to_lcore, 0, (vr_num_cpus *
2964 : sizeof(stats->vis_queue_ierrors_to_lcore)));
2965 120 : return;
2966 : }
2967 :
2968 : static int
2969 158 : __vr_interface_make_req(vr_interface_req *req, struct vr_interface *intf,
2970 : unsigned int core)
2971 : {
2972 : unsigned int cpu, i;
2973 : uint64_t *ip6;
2974 : int ret;
2975 :
2976 : struct vr_interface_settings settings;
2977 : struct vr_interface_bond_info bond_info;
2978 : struct vr_interface_vlan_info vlan_info;
2979 :
2980 158 : req->vifr_core = core;
2981 158 : req->vifr_type = intf->vif_type;
2982 158 : req->vifr_flags = intf->vif_flags;
2983 158 : req->vifr_vrf = intf->vif_vrf;
2984 158 : req->vifr_mcast_vrf = intf->vif_mcast_vrf;
2985 158 : req->vifr_idx = intf->vif_idx;
2986 158 : req->vifr_rid = intf->vif_rid;
2987 158 : req->vifr_transport = intf->vif_transport;
2988 158 : req->vifr_os_idx = intf->vif_os_idx;
2989 158 : req->vifr_mtu = intf->vif_mtu;
2990 158 : req->vifr_nh_id = intf->vif_nh_id;
2991 158 : if (req->vifr_mac_size && req->vifr_mac)
2992 158 : memcpy(req->vifr_mac, intf->vif_mac,
2993 158 : MINIMUM(req->vifr_mac_size, sizeof(intf->vif_mac)));
2994 158 : req->vifr_ip = intf->vif_ip;
2995 158 : ip6 = (uint64_t *)(intf->vif_ip6);
2996 158 : req->vifr_ip6_u = *ip6;
2997 158 : req->vifr_ip6_l = *(ip6 + 1);
2998 158 : req->vifr_mir_id = intf->vif_mirror_id;
2999 :
3000 158 : req->vifr_ref_cnt = intf->vif_users;
3001 :
3002 158 : if (req->vifr_name) {
3003 158 : memcpy(req->vifr_name, intf->vif_name,
3004 : MINIMUM(sizeof(intf->vif_name), VR_INTERFACE_NAME_LEN) - 1);
3005 : }
3006 :
3007 158 : if (intf->vif_parent)
3008 0 : req->vifr_parent_vif_idx = intf->vif_parent->vif_idx;
3009 : else
3010 158 : req->vifr_parent_vif_idx = -1;
3011 :
3012 158 : if (intf->vif_type == VIF_TYPE_VIRTUAL_VLAN) {
3013 0 : req->vifr_vlan_id = intf->vif_vlan_id;
3014 0 : req->vifr_ovlan_id = intf->vif_ovlan_id;
3015 : }
3016 :
3017 158 : if (intf->vif_src_mac) {
3018 0 : req->vifr_src_mac_size = 0;
3019 0 : req->vifr_bridge_idx_size = 0;
3020 0 : for (i = 0; i < VIF_SRC_MACS; i++) {
3021 0 : if (IS_MAC_ZERO((intf->vif_src_mac + (i * VR_ETHER_ALEN))))
3022 0 : continue;
3023 0 : VR_MAC_COPY((req->vifr_src_mac + (i * VR_ETHER_ALEN)),
3024 : (intf->vif_src_mac + (i * VR_ETHER_ALEN)));
3025 0 : req->vifr_src_mac_size += VR_ETHER_ALEN;
3026 0 : req->vifr_bridge_idx[i] =
3027 0 : vif_bridge_get_index(intf->vif_parent, intf,
3028 0 : intf->vif_src_mac + (i * VR_ETHER_ALEN));
3029 0 : req->vifr_bridge_idx_size += sizeof(uint32_t);
3030 : }
3031 : } else {
3032 : /*
3033 : * this is a small hack. we had already allocated the memory in
3034 : * req_get and it is common for all interfaces. how do we tell
3035 : * that the field is not valid - by setting the size to 0.
3036 : */
3037 158 : req->vifr_src_mac_size = 0;
3038 158 : req->vifr_bridge_idx_size = 0;
3039 : }
3040 :
3041 158 : req->vifr_in_mirror_md_size = 0;
3042 158 : if (intf->vif_in_mirror_md_len) {
3043 0 : memcpy(req->vifr_in_mirror_md, intf->vif_in_mirror_md,
3044 0 : intf->vif_in_mirror_md_len);
3045 0 : req->vifr_in_mirror_md_size = intf->vif_in_mirror_md_len;
3046 : }
3047 :
3048 158 : req->vifr_out_mirror_md_size = 0;
3049 158 : if (intf->vif_out_mirror_md_len) {
3050 0 : memcpy(req->vifr_out_mirror_md, intf->vif_out_mirror_md,
3051 0 : intf->vif_out_mirror_md_len);
3052 0 : req->vifr_out_mirror_md_size = intf->vif_out_mirror_md_len;
3053 : }
3054 :
3055 158 : req->vifr_isid = intf->vif_isid;
3056 158 : if (!IS_MAC_ZERO(intf->vif_pbb_mac) && req->vifr_pbb_mac) {
3057 0 : req->vifr_pbb_mac_size = VR_ETHER_ALEN;
3058 0 : VR_MAC_COPY(req->vifr_pbb_mac, intf->vif_pbb_mac);
3059 : } else {
3060 158 : req->vifr_pbb_mac_size = 0;
3061 : }
3062 158 : req->vifr_vhostuser_mode = intf->vif_vhostuser_mode;
3063 :
3064 : /* vif counters */
3065 158 : req->vifr_ibytes = 0;
3066 158 : req->vifr_ipackets = 0;
3067 158 : req->vifr_ierrors = 0;
3068 158 : req->vifr_obytes = 0;
3069 158 : req->vifr_opackets = 0;
3070 158 : req->vifr_oerrors = 0;
3071 : /* queue counters */
3072 158 : req->vifr_queue_ipackets = 0;
3073 2054 : for (i = 0; i < vr_num_cpus; i++)
3074 1896 : req->vifr_queue_ierrors_to_lcore[i] = 0;
3075 158 : req->vifr_queue_ierrors = 0;
3076 158 : req->vifr_queue_opackets = 0;
3077 158 : req->vifr_queue_oerrors = 0;
3078 : /* port counters */
3079 158 : req->vifr_port_ipackets = 0;
3080 158 : req->vifr_port_ierrors = 0;
3081 158 : req->vifr_port_isyscalls = 0;
3082 158 : req->vifr_port_inombufs = 0;
3083 158 : req->vifr_port_opackets = 0;
3084 158 : req->vifr_port_oerrors = 0;
3085 158 : req->vifr_port_osyscalls = 0;
3086 : /* device counters */
3087 158 : req->vifr_dev_ibytes = 0;
3088 158 : req->vifr_dev_ipackets = 0;
3089 158 : req->vifr_dev_ierrors = 0;
3090 158 : req->vifr_dev_inombufs = 0;
3091 158 : req->vifr_dev_obytes = 0;
3092 158 : req->vifr_dev_opackets = 0;
3093 158 : req->vifr_dev_oerrors = 0;
3094 :
3095 : /* call host callback if available */
3096 158 : if (hif_ops->hif_stats_update) {
3097 158 : hif_ops->hif_stats_update(intf, core);
3098 : }
3099 :
3100 158 : if (core == (unsigned)-1) {
3101 : /* summed up stats */
3102 2054 : for (cpu = 0; cpu < vr_num_cpus; cpu++) {
3103 1896 : vr_interface_add_response(req, vif_get_stats(intf, cpu));
3104 : }
3105 0 : } else if (core < vr_num_cpus) {
3106 : /* stats for a specific core */
3107 0 : vr_interface_add_response(req, vif_get_stats(intf, core));
3108 : }
3109 : /* otherwise the conters will be zeros */
3110 :
3111 158 : req->vifr_speed = -1;
3112 158 : req->vifr_duplex = -1;
3113 158 : if (intf->vif_type == VIF_TYPE_PHYSICAL) {
3114 42 : if (!hif_ops->hif_get_settings(intf, &settings)) {
3115 0 : req->vifr_speed = settings.vis_speed;
3116 0 : req->vifr_duplex = settings.vis_duplex;
3117 : }
3118 42 : if (hif_ops->hif_get_bond_info) {
3119 42 : if(!hif_ops->hif_get_bond_info(intf, &bond_info)) {
3120 0 : ret = vr_interface_copy_bond_info(req, &bond_info);
3121 0 : if(ret != 0)
3122 0 : return -ENOMEM;
3123 : }
3124 : }
3125 42 : if (hif_ops->hif_get_vlan_info) {
3126 : /* Intialize vlan tag */
3127 42 : req->vifr_vlan_tag = VLAN_ID_INVALID;
3128 42 : if(!hif_ops->hif_get_vlan_info(intf, &vlan_info)) {
3129 0 : req->vifr_vlan_tag = vlan_info.vlan_id;
3130 0 : req->vifr_vlan_name_size = strlen(vlan_info.vlan_name) + 1;
3131 0 : req->vifr_vlan_name =
3132 0 : vr_zalloc(req->vifr_vlan_name_size * sizeof(uint8_t),
3133 : VR_INTERFACE_OBJECT);
3134 0 : if(!req->vifr_vlan_name)
3135 0 : return -ENOMEM;
3136 0 : snprintf(req->vifr_vlan_name, req->vifr_vlan_name_size,
3137 : "%s", vlan_info.vlan_name);
3138 : }
3139 : }
3140 : }
3141 :
3142 158 : for (i = 0; i < intf->fat_flow_cfg_size; i++) {
3143 0 : req->vifr_fat_flow_protocol_port[i] =
3144 0 : (intf->fat_flow_cfg[i].port) |
3145 0 : (((uint32_t)intf->fat_flow_cfg[i].protocol) << 16) |
3146 0 : (((uint32_t)intf->fat_flow_cfg[i].port_aggr_info) << 24);
3147 0 : req->vifr_fat_flow_src_prefix_h[i] = intf->fat_flow_cfg[i].src_prefix_h;
3148 0 : req->vifr_fat_flow_src_prefix_l[i] = intf->fat_flow_cfg[i].src_prefix_l;
3149 0 : req->vifr_fat_flow_src_prefix_mask[i] =
3150 0 : intf->fat_flow_cfg[i].src_prefix_mask;
3151 0 : req->vifr_fat_flow_src_aggregate_plen[i] =
3152 0 : intf->fat_flow_cfg[i].src_aggregate_plen;
3153 0 : req->vifr_fat_flow_dst_prefix_h[i] =
3154 0 : intf->fat_flow_cfg[i].dst_prefix_h;
3155 0 : req->vifr_fat_flow_dst_prefix_l[i] =
3156 0 : intf->fat_flow_cfg[i].dst_prefix_l;
3157 0 : req->vifr_fat_flow_dst_prefix_mask[i] =
3158 0 : intf->fat_flow_cfg[i].dst_prefix_mask;
3159 0 : req->vifr_fat_flow_dst_aggregate_plen[i] =
3160 0 : intf->fat_flow_cfg[i].dst_aggregate_plen;
3161 : }
3162 :
3163 : /* Fill the ipv4 & ipv6 exclude lists; NOTE: The prefix lengths are not filled */
3164 158 : for (i = 0; i < req->vifr_fat_flow_exclude_ip_list_size; i++) {
3165 0 : req->vifr_fat_flow_exclude_ip_list[i] = (uint64_t) intf->vif_fat_flow_ipv4_exclude_list[i];
3166 : }
3167 :
3168 158 : for (i = 0; i < req->vifr_fat_flow_exclude_ip6_u_list_size; i++) {
3169 0 : req->vifr_fat_flow_exclude_ip6_u_list[i] = intf->vif_fat_flow_ipv6_high_exclude_list[i];
3170 0 : req->vifr_fat_flow_exclude_ip6_l_list[i] = intf->vif_fat_flow_ipv6_low_exclude_list[i];
3171 : }
3172 :
3173 158 : req->vifr_qos_map_index = intf->vif_qos_map_index;
3174 158 : req->vifr_dpackets = vr_interface_get_drops(intf);
3175 158 : return 0;
3176 : }
3177 :
3178 : static int
3179 158 : vr_interface_make_req(vr_interface_req *req, struct vr_interface *vif,
3180 : unsigned int core)
3181 : {
3182 : unsigned int fat_flow_config_size;
3183 : int ret;
3184 :
3185 158 : fat_flow_config_size = vif->fat_flow_cfg_size;
3186 :
3187 158 : if (fat_flow_config_size) {
3188 0 : req->vifr_fat_flow_protocol_port =
3189 0 : vr_zalloc(fat_flow_config_size * sizeof(uint32_t),
3190 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3191 0 : if (!req->vifr_fat_flow_protocol_port) {
3192 0 : return -ENOMEM;
3193 : }
3194 0 : req->vifr_fat_flow_protocol_port_size = fat_flow_config_size;
3195 :
3196 0 : req->vifr_fat_flow_src_prefix_h =
3197 0 : vr_zalloc(fat_flow_config_size * sizeof(uint64_t),
3198 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3199 0 : if (!req->vifr_fat_flow_src_prefix_h) {
3200 0 : return -ENOMEM;
3201 : }
3202 0 : req->vifr_fat_flow_src_prefix_h_size = fat_flow_config_size;
3203 :
3204 0 : req->vifr_fat_flow_src_prefix_l =
3205 0 : vr_zalloc(fat_flow_config_size * sizeof(uint64_t),
3206 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3207 0 : if (!req->vifr_fat_flow_src_prefix_l) {
3208 0 : return -ENOMEM;
3209 : }
3210 0 : req->vifr_fat_flow_src_prefix_l_size = fat_flow_config_size;
3211 :
3212 0 : req->vifr_fat_flow_src_prefix_mask =
3213 0 : vr_zalloc(fat_flow_config_size * sizeof(uint8_t),
3214 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3215 0 : if (!req->vifr_fat_flow_src_prefix_mask) {
3216 0 : return -ENOMEM;
3217 : }
3218 0 : req->vifr_fat_flow_src_prefix_mask_size = fat_flow_config_size;
3219 :
3220 0 : req->vifr_fat_flow_src_aggregate_plen =
3221 0 : vr_zalloc(fat_flow_config_size * sizeof(uint8_t),
3222 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3223 0 : if (!req->vifr_fat_flow_src_aggregate_plen) {
3224 0 : return -ENOMEM;
3225 : }
3226 0 : req->vifr_fat_flow_src_aggregate_plen_size = fat_flow_config_size;
3227 :
3228 0 : req->vifr_fat_flow_dst_prefix_h =
3229 0 : vr_zalloc(fat_flow_config_size * sizeof(uint64_t),
3230 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3231 0 : if (!req->vifr_fat_flow_dst_prefix_h) {
3232 0 : return -ENOMEM;
3233 : }
3234 0 : req->vifr_fat_flow_dst_prefix_h_size = fat_flow_config_size;
3235 :
3236 0 : req->vifr_fat_flow_dst_prefix_l =
3237 0 : vr_zalloc(fat_flow_config_size * sizeof(uint64_t),
3238 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3239 0 : if (!req->vifr_fat_flow_dst_prefix_l) {
3240 0 : return -ENOMEM;
3241 : }
3242 0 : req->vifr_fat_flow_dst_prefix_l_size = fat_flow_config_size;
3243 :
3244 0 : req->vifr_fat_flow_dst_prefix_mask =
3245 0 : vr_zalloc(fat_flow_config_size * sizeof(uint8_t),
3246 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3247 0 : if (!req->vifr_fat_flow_dst_prefix_mask) {
3248 0 : return -ENOMEM;
3249 : }
3250 0 : req->vifr_fat_flow_dst_prefix_mask_size = fat_flow_config_size;
3251 :
3252 0 : req->vifr_fat_flow_dst_aggregate_plen =
3253 0 : vr_zalloc(fat_flow_config_size * sizeof(uint8_t),
3254 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3255 0 : if (!req->vifr_fat_flow_dst_aggregate_plen) {
3256 0 : return -ENOMEM;
3257 : }
3258 0 : req->vifr_fat_flow_dst_aggregate_plen_size = fat_flow_config_size;
3259 : }
3260 :
3261 158 : if (vif->vif_fat_flow_ipv4_exclude_list_size) {
3262 0 : req->vifr_fat_flow_exclude_ip_list = vr_zalloc(vif->vif_fat_flow_ipv4_exclude_list_size * sizeof(uint64_t),
3263 : VR_INTERFACE_FAT_FLOW_IPV4_EXCLUDE_LIST_OBJECT);
3264 0 : if (!req->vifr_fat_flow_exclude_ip_list) {
3265 0 : return -ENOMEM;
3266 : }
3267 0 : req->vifr_fat_flow_exclude_ip_list_size = vif->vif_fat_flow_ipv4_exclude_list_size;
3268 : }
3269 :
3270 158 : if (vif->vif_fat_flow_ipv6_exclude_list_size) {
3271 0 : req->vifr_fat_flow_exclude_ip6_u_list = vr_zalloc(vif->vif_fat_flow_ipv6_exclude_list_size * sizeof(uint64_t),
3272 : VR_INTERFACE_FAT_FLOW_IPV6_EXCLUDE_LIST_OBJECT);
3273 0 : if (!req->vifr_fat_flow_exclude_ip6_u_list) {
3274 0 : return -ENOMEM;
3275 : }
3276 0 : req->vifr_fat_flow_exclude_ip6_u_list_size = vif->vif_fat_flow_ipv6_exclude_list_size;
3277 0 : req->vifr_fat_flow_exclude_ip6_l_list = vr_zalloc(vif->vif_fat_flow_ipv6_exclude_list_size * sizeof(uint64_t),
3278 : VR_INTERFACE_FAT_FLOW_IPV6_EXCLUDE_LIST_OBJECT);
3279 0 : if (!req->vifr_fat_flow_exclude_ip6_l_list) {
3280 0 : return -ENOMEM;
3281 : }
3282 0 : req->vifr_fat_flow_exclude_ip6_l_list_size = vif->vif_fat_flow_ipv6_exclude_list_size;
3283 : }
3284 :
3285 158 : ret = __vr_interface_make_req(req, vif, core);
3286 158 : if(ret != 0)
3287 0 : return -ENOMEM;
3288 158 : return 0;
3289 : }
3290 :
3291 : unsigned int
3292 163 : vr_interface_req_get_size(void *req_p)
3293 : {
3294 : unsigned int size;
3295 163 : vr_interface_req *req = (vr_interface_req *)req_p;
3296 :
3297 :
3298 : /*
3299 : * Standard interface request size + both ingress and egress
3300 : * metadata size
3301 : */
3302 163 : size = ((4 * sizeof(*req)) + (2 * VIF_MAX_MIRROR_MD_SIZE));
3303 163 : if (req->vifr_queue_ierrors_to_lcore)
3304 158 : size += (vr_num_cpus * sizeof(int64_t));
3305 :
3306 163 : return size;
3307 : }
3308 :
3309 : static vr_interface_req *
3310 158 : vr_interface_req_get(void)
3311 : {
3312 : vr_interface_req *req;
3313 :
3314 158 : req = vr_zalloc(sizeof(*req), VR_INTERFACE_REQ_OBJECT);
3315 158 : if (!req)
3316 0 : return req;
3317 :
3318 158 : req->vifr_mac = vr_zalloc(VR_ETHER_ALEN, VR_INTERFACE_REQ_MAC_OBJECT);
3319 158 : if (req->vifr_mac)
3320 158 : req->vifr_mac_size = VR_ETHER_ALEN;
3321 :
3322 158 : req->vifr_src_mac = vr_zalloc(VR_ETHER_ALEN * VIF_SRC_MACS, VR_INTERFACE_REQ_MAC_OBJECT);
3323 158 : if (req->vifr_src_mac)
3324 158 : req->vifr_src_mac_size = 0;
3325 :
3326 158 : req->vifr_bridge_idx = vr_zalloc(sizeof(uint32_t)* VIF_SRC_MACS,
3327 : VR_INTERFACE_REQ_BRIDGE_ID_OBJECT);
3328 158 : if (req->vifr_bridge_idx)
3329 158 : req->vifr_bridge_idx_size = 0;
3330 :
3331 158 : req->vifr_name = vr_zalloc(VR_INTERFACE_NAME_LEN,
3332 : VR_INTERFACE_REQ_NAME_OBJECT);
3333 :
3334 158 : req->vifr_queue_ierrors_to_lcore = vr_zalloc(vr_num_cpus * sizeof(uint64_t),
3335 : VR_INTERFACE_REQ_TO_LCORE_ERRORS_OBJECT);
3336 158 : if (req->vifr_queue_ierrors_to_lcore)
3337 158 : req->vifr_queue_ierrors_to_lcore_size = 0;
3338 :
3339 158 : req->vifr_in_mirror_md_size = 0;
3340 158 : req->vifr_in_mirror_md = vr_zalloc(VIF_MAX_MIRROR_MD_SIZE,
3341 : VR_INTERFACE_REQ_MIRROR_META_OBJECT);
3342 :
3343 158 : req->vifr_out_mirror_md_size = 0;
3344 158 : req->vifr_out_mirror_md = vr_zalloc(VIF_MAX_MIRROR_MD_SIZE,
3345 : VR_INTERFACE_REQ_MIRROR_META_OBJECT);
3346 158 : req->vifr_pbb_mac = vr_zalloc(VR_ETHER_ALEN,
3347 : VR_INTERFACE_REQ_PBB_MAC_OBJECT);
3348 :
3349 158 : return req;
3350 : }
3351 :
3352 :
3353 : static void
3354 158 : vr_interface_req_free_fat_flow_config(vr_interface_req *req)
3355 : {
3356 158 : if (req->vifr_fat_flow_protocol_port) {
3357 0 : vr_free(req->vifr_fat_flow_protocol_port,
3358 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3359 0 : req->vifr_fat_flow_protocol_port = NULL;
3360 0 : req->vifr_fat_flow_protocol_port_size = 0;
3361 : }
3362 :
3363 158 : if (req->vifr_fat_flow_src_prefix_h) {
3364 0 : vr_free(req->vifr_fat_flow_src_prefix_h,
3365 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3366 0 : req->vifr_fat_flow_src_prefix_h = NULL;
3367 0 : req->vifr_fat_flow_src_prefix_h_size = 0;
3368 : }
3369 :
3370 158 : if (req->vifr_fat_flow_src_prefix_l) {
3371 0 : vr_free(req->vifr_fat_flow_src_prefix_l,
3372 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3373 0 : req->vifr_fat_flow_src_prefix_l = NULL;
3374 0 : req->vifr_fat_flow_src_prefix_l_size = 0;
3375 : }
3376 :
3377 158 : if (req->vifr_fat_flow_src_prefix_mask) {
3378 0 : vr_free(req->vifr_fat_flow_src_prefix_mask,
3379 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3380 0 : req->vifr_fat_flow_src_prefix_mask = NULL;
3381 0 : req->vifr_fat_flow_src_prefix_mask_size = 0;
3382 : }
3383 :
3384 158 : if (req->vifr_fat_flow_src_aggregate_plen) {
3385 0 : vr_free(req->vifr_fat_flow_src_aggregate_plen,
3386 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3387 0 : req->vifr_fat_flow_src_aggregate_plen = NULL;
3388 0 : req->vifr_fat_flow_src_aggregate_plen_size = 0;
3389 : }
3390 :
3391 158 : if (req->vifr_fat_flow_dst_prefix_h) {
3392 0 : vr_free(req->vifr_fat_flow_dst_prefix_h,
3393 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3394 0 : req->vifr_fat_flow_dst_prefix_h = NULL;
3395 0 : req->vifr_fat_flow_dst_prefix_h_size = 0;
3396 : }
3397 :
3398 158 : if (req->vifr_fat_flow_dst_prefix_l) {
3399 0 : vr_free(req->vifr_fat_flow_dst_prefix_l,
3400 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3401 0 : req->vifr_fat_flow_dst_prefix_l = NULL;
3402 0 : req->vifr_fat_flow_dst_prefix_l_size = 0;
3403 : }
3404 :
3405 158 : if (req->vifr_fat_flow_dst_prefix_mask) {
3406 0 : vr_free(req->vifr_fat_flow_dst_prefix_mask,
3407 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3408 0 : req->vifr_fat_flow_dst_prefix_mask = NULL;
3409 0 : req->vifr_fat_flow_dst_prefix_mask_size = 0;
3410 : }
3411 :
3412 158 : if (req->vifr_fat_flow_dst_aggregate_plen) {
3413 0 : vr_free(req->vifr_fat_flow_dst_aggregate_plen,
3414 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3415 0 : req->vifr_fat_flow_dst_aggregate_plen = NULL;
3416 0 : req->vifr_fat_flow_dst_aggregate_plen_size = 0;
3417 : }
3418 :
3419 158 : if (req->vifr_fat_flow_exclude_ip_list) {
3420 0 : vr_free(req->vifr_fat_flow_exclude_ip_list, VR_INTERFACE_FAT_FLOW_IPV4_EXCLUDE_LIST_OBJECT);
3421 0 : req->vifr_fat_flow_exclude_ip_list = NULL;
3422 0 : req->vifr_fat_flow_exclude_ip_list_size = 0;
3423 : }
3424 158 : if (req->vifr_fat_flow_exclude_ip6_u_list) {
3425 0 : vr_free(req->vifr_fat_flow_exclude_ip6_u_list, VR_INTERFACE_FAT_FLOW_IPV6_EXCLUDE_LIST_OBJECT);
3426 0 : req->vifr_fat_flow_exclude_ip6_u_list = NULL;
3427 0 : req->vifr_fat_flow_exclude_ip6_u_list_size = 0;
3428 : }
3429 158 : if (req->vifr_fat_flow_exclude_ip6_l_list) {
3430 0 : vr_free(req->vifr_fat_flow_exclude_ip6_l_list, VR_INTERFACE_FAT_FLOW_IPV6_EXCLUDE_LIST_OBJECT);
3431 0 : req->vifr_fat_flow_exclude_ip6_l_list = NULL;
3432 0 : req->vifr_fat_flow_exclude_ip6_l_list_size = 0;
3433 : }
3434 :
3435 158 : return;
3436 : }
3437 :
3438 : static void
3439 158 : vr_interface_req_destroy(vr_interface_req *req)
3440 : {
3441 158 : if (!req)
3442 0 : return;
3443 :
3444 158 : if (req->vifr_mac) {
3445 158 : vr_free(req->vifr_mac, VR_INTERFACE_REQ_MAC_OBJECT);
3446 158 : req->vifr_mac_size = 0;
3447 : }
3448 :
3449 158 : if (req->vifr_src_mac) {
3450 158 : vr_free(req->vifr_src_mac, VR_INTERFACE_REQ_MAC_OBJECT);
3451 158 : req->vifr_src_mac_size = 0;
3452 : }
3453 :
3454 158 : if (req->vifr_bridge_idx) {
3455 158 : vr_free(req->vifr_bridge_idx, VR_INTERFACE_REQ_BRIDGE_ID_OBJECT);
3456 158 : req->vifr_bridge_idx_size = 0;
3457 : }
3458 :
3459 158 : if (req->vifr_name)
3460 158 : vr_free(req->vifr_name, VR_INTERFACE_REQ_NAME_OBJECT);
3461 :
3462 158 : if (req->vifr_queue_ierrors_to_lcore) {
3463 158 : vr_free(req->vifr_queue_ierrors_to_lcore,
3464 : VR_INTERFACE_REQ_TO_LCORE_ERRORS_OBJECT);
3465 158 : req->vifr_queue_ierrors_to_lcore_size = 0;
3466 : }
3467 :
3468 158 : if (req->vifr_in_mirror_md) {
3469 158 : vr_free(req->vifr_in_mirror_md,
3470 : VR_INTERFACE_REQ_MIRROR_META_OBJECT);
3471 158 : req->vifr_in_mirror_md_size = 0;
3472 158 : req->vifr_in_mirror_md = NULL;
3473 : }
3474 :
3475 158 : if (req->vifr_out_mirror_md) {
3476 158 : vr_free(req->vifr_out_mirror_md,
3477 : VR_INTERFACE_REQ_MIRROR_META_OBJECT);
3478 158 : req->vifr_out_mirror_md_size = 0;
3479 158 : req->vifr_out_mirror_md = NULL;
3480 : }
3481 :
3482 158 : if (req->vifr_pbb_mac) {
3483 158 : vr_free(req->vifr_pbb_mac,
3484 : VR_INTERFACE_REQ_PBB_MAC_OBJECT);
3485 158 : req->vifr_pbb_mac = NULL;
3486 158 : req->vifr_pbb_mac_size = 0;
3487 : }
3488 :
3489 158 : if(req->vifr_fab_name) {
3490 0 : vr_free(req->vifr_fab_name,
3491 : VR_INTERFACE_BOND_OBJECT);
3492 0 : req->vifr_fab_name_size = 0;
3493 : }
3494 :
3495 158 : if(req->vifr_fab_drv_name) {
3496 0 : vr_free(req->vifr_fab_drv_name,
3497 : VR_INTERFACE_BOND_OBJECT);
3498 0 : req->vifr_fab_name_size = 0;
3499 : }
3500 :
3501 158 : if(req->vifr_bond_slave_name) {
3502 0 : vr_free(req->vifr_bond_slave_name,
3503 : VR_INTERFACE_BOND_OBJECT);
3504 0 : req->vifr_bond_slave_name_size = 0;
3505 : }
3506 :
3507 158 : if(req->vifr_bond_slave_drv_name) {
3508 0 : vr_free(req->vifr_bond_slave_drv_name,
3509 : VR_INTERFACE_BOND_OBJECT);
3510 0 : req->vifr_bond_slave_drv_name_size = 0;
3511 : }
3512 :
3513 158 : if(req->vifr_vlan_name) {
3514 0 : vr_free(req->vifr_vlan_name,
3515 : VR_INTERFACE_OBJECT);
3516 0 : req->vifr_vlan_name_size = 0;
3517 : }
3518 :
3519 158 : vr_interface_req_free_fat_flow_config(req);
3520 :
3521 158 : vr_free(req, VR_INTERFACE_REQ_OBJECT);
3522 :
3523 158 : return;
3524 : }
3525 :
3526 : static int
3527 158 : vr_interface_get(vr_interface_req *req)
3528 : {
3529 158 : int ret = 0, obj_cnt = 0;
3530 : struct vr_message_multi mm;
3531 : vr_response resp;
3532 : struct vrouter *router;
3533 158 : vr_interface_req *vif_resp = NULL;
3534 158 : vr_drop_stats_req *drop_resp = NULL;
3535 158 : struct vr_interface *vif = NULL;
3536 :
3537 158 : resp.h_op = SANDESH_OP_RESPONSE;
3538 158 : mm.vr_mm_object_type[obj_cnt] = VR_RESPONSE_OBJECT_ID;
3539 158 : mm.vr_mm_object[obj_cnt] = &resp;
3540 158 : obj_cnt++;
3541 :
3542 158 : router = vrouter_get(req->vifr_rid);
3543 158 : if (!router) {
3544 0 : ret = -ENODEV;
3545 0 : goto generate_response;
3546 : }
3547 :
3548 158 : if ((unsigned int)req->vifr_idx >= router->vr_max_interfaces)
3549 0 : vif = __vrouter_get_interface_os(router, req->vifr_os_idx);
3550 : else
3551 158 : vif = __vrouter_get_interface(router, req->vifr_idx);
3552 :
3553 158 : if (!vif) {
3554 0 : vr_printf("Vrouter: %s:%d vif is NULL for vifr_idx: %d \n",
3555 : __func__, __LINE__, req->vifr_idx);
3556 0 : ret = -ENOENT;
3557 0 : goto generate_response;
3558 : }
3559 :
3560 158 : vif_resp = vr_interface_req_get();
3561 158 : if (!vif_resp) {
3562 0 : ret = -ENOMEM;
3563 0 : goto generate_response;
3564 : }
3565 :
3566 158 : ret = vr_interface_make_req(vif_resp, vif, (unsigned)(req->vifr_core - 1));
3567 158 : if (ret < 0)
3568 0 : goto generate_response;
3569 :
3570 158 : mm.vr_mm_object_type[obj_cnt] = VR_INTERFACE_OBJECT_ID;
3571 158 : mm.vr_mm_object[obj_cnt] = vif_resp;
3572 158 : obj_cnt++;
3573 :
3574 158 : if (req->vifr_flags & VIF_FLAG_GET_DROP_STATS) {
3575 0 : drop_resp = vr_zalloc(sizeof(*drop_resp), VR_DROP_STATS_REQ_OBJECT);
3576 0 : if (!drop_resp) {
3577 0 : ret = -ENOMEM;
3578 0 : goto generate_response;
3579 : }
3580 :
3581 0 : if (!vif->vif_pcpu_drop_stats)
3582 0 : drop_resp->vds_pcpu_stats_failure_status = 1;
3583 :
3584 0 : vr_drop_stats_get_vif_stats(drop_resp, vif);
3585 :
3586 0 : mm.vr_mm_object_type[obj_cnt] = VR_DROP_STATS_OBJECT_ID;
3587 0 : mm.vr_mm_object[obj_cnt] = drop_resp;
3588 0 : obj_cnt++;
3589 :
3590 : /* adds in stats for pkts which were offloaded on NIC and does debug
3591 : comparison to check if matching entry is programmed on NIC */
3592 0 : ret = vr_offload_interface_get(vif_resp);
3593 : }
3594 :
3595 158 : generate_response:
3596 158 : mm.vr_mm_object_count = obj_cnt;
3597 158 : resp.resp_code = ret;
3598 158 : vr_message_multi_response(&mm);
3599 :
3600 158 : if (vif_resp)
3601 158 : vr_interface_req_destroy(vif_resp);
3602 :
3603 158 : if (drop_resp)
3604 0 : vr_free(drop_resp, VR_DROP_STATS_REQ_OBJECT);
3605 :
3606 158 : return 0;
3607 : }
3608 :
3609 : static int
3610 0 : vr_interface_dump(vr_interface_req *r)
3611 : {
3612 0 : int ret = 0;
3613 : unsigned int i;
3614 0 : vr_interface_req *resp = NULL;
3615 : struct vr_interface *vif;
3616 0 : struct vrouter *router = vrouter_get(r->vifr_rid);
3617 0 : struct vr_message_dumper *dumper = NULL;
3618 0 : vr_drop_stats_req *drop_resp = NULL;
3619 :
3620 0 : if (!router && (ret = -ENODEV))
3621 0 : goto generate_response;
3622 :
3623 0 : if ((unsigned int)(r->vifr_marker + 1) >= router->vr_max_interfaces)
3624 0 : goto generate_response;
3625 :
3626 0 : dumper = vr_message_dump_init(r);
3627 0 : if (!dumper) {
3628 0 : ret = -ENOMEM;
3629 0 : goto generate_response;
3630 : }
3631 :
3632 0 : resp = vr_interface_req_get();
3633 0 : if (!resp) {
3634 0 : ret = -ENOMEM;
3635 0 : goto generate_response;
3636 : }
3637 :
3638 0 : drop_resp = vr_zalloc(sizeof(*drop_resp), VR_DROP_STATS_REQ_OBJECT);
3639 0 : if (!drop_resp) {
3640 0 : ret = -ENOMEM;
3641 0 : goto generate_response;
3642 : }
3643 :
3644 0 : for (i = (unsigned int)(r->vifr_marker + 1);
3645 0 : i < router->vr_max_interfaces; i++) {
3646 0 : vif = router->vr_interfaces[i];
3647 0 : if (vif) {
3648 : /* zero vifr_core means to sum up all the per-core stats */
3649 0 : vr_interface_make_req(resp, vif, (unsigned)(r->vifr_core - 1));
3650 :
3651 : /* let hw offload fill in relevant fields */
3652 0 : vr_offload_interface_get(resp);
3653 :
3654 0 : ret = vr_message_dump_object(dumper, VR_INTERFACE_OBJECT_ID, resp);
3655 0 : if (ret <= 0)
3656 0 : break;
3657 :
3658 0 : if (r->vifr_flags & VIF_FLAG_GET_DROP_STATS) {
3659 0 : if (!vif->vif_pcpu_drop_stats)
3660 0 : drop_resp->vds_pcpu_stats_failure_status = 1;
3661 :
3662 0 : vr_drop_stats_get_vif_stats(drop_resp, vif);
3663 :
3664 0 : ret = vr_message_dump_object(dumper, VR_DROP_STATS_OBJECT_ID, drop_resp);
3665 : /*
3666 : * If we succed in interface dump, but fail to add drop
3667 : * stats dump, the caller would retry the interface
3668 : * again
3669 : */
3670 0 : if (ret <= 0)
3671 0 : break;
3672 : }
3673 0 : vr_interface_req_free_fat_flow_config(resp);
3674 : }
3675 : }
3676 :
3677 0 : generate_response:
3678 0 : vr_message_dump_exit(dumper, ret);
3679 0 : if (resp)
3680 0 : vr_interface_req_destroy(resp);
3681 :
3682 0 : if (drop_resp)
3683 0 : vr_free(drop_resp, VR_DROP_STATS_REQ_OBJECT);
3684 :
3685 0 : return 0;
3686 : }
3687 :
3688 : static int
3689 10 : vr_interface_stats_reset(struct vr_interface *vif, int core)
3690 : {
3691 10 : int cpu = 0;
3692 :
3693 10 : if (hif_ops->hif_stats_update)
3694 10 : hif_ops->hif_clear_stats(vif);
3695 :
3696 : /* Clearing Tx/Rx packets on all cores */
3697 10 : if(core == -1) {
3698 130 : for (cpu = 0; cpu < vr_num_cpus; cpu++) {
3699 120 : vr_vif_stats_reset(&vif->vif_stats[cpu]);
3700 : }
3701 : } else {
3702 0 : if(core > (vr_num_cpus - 1)) {
3703 0 : vr_printf("vif clear stats: Invalid core id: %d\n", core);
3704 0 : return -1;
3705 : } else {
3706 0 : vr_vif_stats_reset(&vif->vif_stats[core]);
3707 : }
3708 : }
3709 10 : return 0;
3710 : }
3711 :
3712 : static int
3713 10 : vr_interface_dropstats_reset(struct vr_interface *vif, int core)
3714 : {
3715 10 : int reason = 0, cpu = 0;
3716 : uint8_t *data;
3717 :
3718 10 : if (core == -1) {
3719 10 : memset(vif->vif_drop_stats, 0, sizeof(uint64_t) * VP_DROP_MAX);
3720 130 : for (cpu = 0; cpu < vr_num_cpus; cpu++) {
3721 6720 : for (reason = 0; reason < VP_DROP_MAX; reason++) {
3722 6600 : data = vr_btable_get(vif->vif_pcpu_drop_stats,
3723 6600 : ((cpu * VP_DROP_MAX) + reason));
3724 6600 : *data = 0;
3725 : }
3726 : }
3727 : } else {
3728 0 : if (core > (vr_num_cpus - 1)) {
3729 0 : vr_printf("vif clear dropstats: invalid core id: %d\n", core);
3730 0 : return -1;
3731 : }
3732 0 : for (reason = 0; reason < VP_DROP_MAX; reason++) {
3733 0 : data = vr_btable_get(vif->vif_pcpu_drop_stats,
3734 0 : ((core * VP_DROP_MAX) + reason));
3735 0 : *data = 0;
3736 : }
3737 : }
3738 10 : return 0;
3739 : }
3740 :
3741 : static int
3742 5 : vr_interface_clear_stats(vr_interface_req *r)
3743 : {
3744 5 : int i, ret = 0;
3745 : struct vr_interface *vif;
3746 5 : struct vrouter *router = vrouter_get(0);
3747 5 : vr_interface_req *response = NULL;
3748 5 : int core = r->vifr_core - 1;
3749 :
3750 5 : response = vr_zalloc(sizeof(*response), VR_INTERFACE_REQ_OBJECT);
3751 5 : if (!response && (ret = -ENOMEM))
3752 0 : goto exit_get;
3753 :
3754 5 : if(r->vifr_idx == -1) {
3755 8712 : for (i = 0; i < router->vr_max_interfaces; i++) {
3756 8710 : vif = router->vr_interfaces[i];
3757 8710 : if(vif) {
3758 7 : ret = vr_interface_stats_reset(vif, core);
3759 7 : if(ret < 0)
3760 0 : goto exit_get;
3761 7 : ret = vr_interface_dropstats_reset(vif, core);
3762 7 : if (ret < 0)
3763 0 : goto exit_get;
3764 : }
3765 : }
3766 : } else {
3767 3 : vif = router->vr_interfaces[r->vifr_idx];
3768 3 : if (vif) {
3769 3 : ret = vr_interface_stats_reset(vif, core);
3770 3 : if(ret < 0)
3771 0 : goto exit_get;
3772 3 : ret = vr_interface_dropstats_reset(vif, core);
3773 3 : if (ret < 0)
3774 0 : goto exit_get;
3775 :
3776 3 : response->vifr_name = vr_zalloc(VR_INTERFACE_NAME_LEN,
3777 : VR_INTERFACE_REQ_NAME_OBJECT);
3778 3 : if (response->vifr_name) {
3779 3 : memcpy(response->vifr_name, vif->vif_name,
3780 : MINIMUM(sizeof(vif->vif_name), VR_INTERFACE_NAME_LEN) - 1);
3781 : } else {
3782 0 : ret = -ENOMEM;
3783 0 : goto exit_get;
3784 : }
3785 :
3786 : } else {
3787 0 : vr_printf("vif clear stats: Invalid vif id: %d\n", r->vifr_idx);
3788 0 : goto exit_get;
3789 : }
3790 : }
3791 5 : response->h_op = SANDESH_OP_RESET;
3792 5 : response->vifr_core = r->vifr_core;
3793 5 : response->vifr_idx = r->vifr_idx;
3794 :
3795 5 : exit_get:
3796 5 : vr_message_response(VR_INTERFACE_OBJECT_ID, ret ? NULL : response, ret, false);
3797 :
3798 5 : if(response->vifr_name)
3799 3 : vr_free(response->vifr_name, VR_INTERFACE_REQ_NAME_OBJECT);
3800 5 : if (response != NULL)
3801 5 : vr_free(response, VR_INTERFACE_REQ_OBJECT);
3802 :
3803 5 : return ret;
3804 : }
3805 :
3806 :
3807 : void
3808 845 : vr_interface_req_process(void *s_req)
3809 : {
3810 : int ret;
3811 845 : vr_interface_req *req = (vr_interface_req *)s_req;
3812 845 : bool need_response = true;
3813 :
3814 845 : switch (req->h_op) {
3815 339 : case SANDESH_OP_ADD:
3816 339 : ret = vr_interface_add(req, need_response);
3817 339 : break;
3818 :
3819 158 : case SANDESH_OP_GET:
3820 158 : ret = vr_interface_get(req);
3821 158 : break;
3822 :
3823 343 : case SANDESH_OP_DEL:
3824 343 : ret = vr_interface_delete(req, need_response);
3825 343 : break;
3826 :
3827 0 : case SANDESH_OP_DUMP:
3828 0 : ret = vr_interface_dump(req);
3829 0 : break;
3830 :
3831 5 : case SANDESH_OP_RESET:
3832 5 : ret = vr_interface_clear_stats(req);
3833 5 : break;
3834 :
3835 0 : default:
3836 0 : ret = -EOPNOTSUPP;
3837 0 : goto error;
3838 : }
3839 :
3840 845 : return;
3841 :
3842 0 : error:
3843 0 : vr_send_response(ret);
3844 0 : return;
3845 : }
3846 :
3847 : unsigned int
3848 0 : vif_vrf_table_get_nh(struct vr_interface *vif, unsigned short vlan)
3849 : {
3850 0 : if (vlan >= VLAN_ID_INVALID || !vif_is_service(vif))
3851 0 : return vif->vif_nh_id;
3852 :
3853 0 : if (!vif->vif_vrf_table)
3854 0 : return vif->vif_nh_id;
3855 :
3856 0 : return vif->vif_vrf_table[vlan].va_nh_id;
3857 : }
3858 :
3859 : int
3860 0 : vif_vrf_table_get(struct vr_interface *vif, vr_vrf_assign_req *req)
3861 : {
3862 0 : if (!vif_is_service(vif))
3863 0 : return -EINVAL;
3864 :
3865 0 : if (!vif->vif_vrf_table)
3866 0 : return -ENOMEM;
3867 :
3868 0 : if (req->var_vlan_id >= VIF_VRF_TABLE_ENTRIES)
3869 0 : return -EINVAL;
3870 :
3871 0 : req->var_vif_vrf = vif->vif_vrf_table[req->var_vlan_id].va_vrf;
3872 0 : req->var_nh_id = vif->vif_vrf_table[req->var_vlan_id].va_nh_id;
3873 0 : return 0;
3874 : }
3875 :
3876 : /*
3877 : * the logic here is slightly hacky. 'agent' cannot ensure that
3878 : * the service flag is unset only after all vrf table entries are
3879 : * deleted. so, it is possible that the service flag is unset and
3880 : * requests can still come for deletion of vrf table entries, and
3881 : * error cannot be returned in such cases. so,reference counts are
3882 : * taken and the table is freed only when the reference count goes
3883 : * to zero or when the interface is actually deleted
3884 : */
3885 : int
3886 0 : vif_vrf_table_set(struct vr_interface *vif, unsigned int vlan,
3887 : int vrf, unsigned int nh_id)
3888 : {
3889 0 : int ret = 0;
3890 :
3891 0 : if (!vif->vif_vrf_table) {
3892 : /*
3893 : * 1. if the service flag is not set, then we make the interface
3894 : * as the service interface
3895 : *
3896 : * 2. service flag is set and we were not able to allocate
3897 : * the table
3898 : */
3899 0 : if (!vif_is_service(vif)) {
3900 0 : ret = vr_interface_service_enable(vif);
3901 0 : if (ret)
3902 0 : return ret;
3903 0 : vif->vif_flags |= VIF_FLAG_SERVICE_IF;
3904 : } else {
3905 0 : return -ENOMEM;
3906 : }
3907 : }
3908 :
3909 0 : if (vlan >= VIF_VRF_TABLE_ENTRIES)
3910 0 : return -EINVAL;
3911 :
3912 : /*
3913 : * increment reference count only when the old entry was -1
3914 : * and the new entry is not equal to -1.
3915 : *
3916 : * decrement reference count only when the old entry was >= 0
3917 : * and the new entry is < 0
3918 : */
3919 0 : if (vif->vif_vrf_table[vlan].va_vrf < 0) {
3920 0 : if (vrf >= 0)
3921 0 : vif->vif_vrf_table_users++;
3922 : } else {
3923 0 : if (vrf < 0)
3924 0 : vif->vif_vrf_table_users--;
3925 : }
3926 :
3927 0 : vif->vif_vrf_table[vlan].va_vrf = vrf;
3928 0 : vif->vif_vrf_table[vlan].va_nh_id = nh_id;
3929 :
3930 : /*
3931 : * on last delete, if the service flag is not set, free
3932 : * the table
3933 : */
3934 0 : if (!(vif->vif_flags & VIF_FLAG_SERVICE_IF) &&
3935 0 : !vif->vif_vrf_table_users) {
3936 0 : vr_free(vif->vif_vrf_table, VR_INTERFACE_VRF_TABLE_OBJECT);
3937 0 : vif->vif_vrf_table = NULL;
3938 : }
3939 :
3940 0 : return 0;
3941 : }
3942 :
3943 : static unsigned int
3944 57 : vif_fat_flow_get_proto_index(uint8_t proto)
3945 : {
3946 57 : unsigned int proto_index = VIF_FAT_FLOW_NOPROTO_INDEX;
3947 :
3948 57 : switch (proto) {
3949 19 : case VR_IP_PROTO_TCP:
3950 19 : proto_index = VIF_FAT_FLOW_TCP_INDEX;
3951 19 : break;
3952 :
3953 6 : case VR_IP_PROTO_UDP:
3954 6 : proto_index = VIF_FAT_FLOW_UDP_INDEX;
3955 6 : break;
3956 :
3957 0 : case VR_IP_PROTO_SCTP:
3958 0 : proto_index = VIF_FAT_FLOW_SCTP_INDEX;
3959 0 : break;
3960 :
3961 32 : default:
3962 32 : break;
3963 : }
3964 :
3965 57 : return proto_index;
3966 : }
3967 :
3968 : static void
3969 0 : vif_fat_flow_free(uint8_t **mem)
3970 : {
3971 : int i;
3972 :
3973 0 : if (!mem)
3974 0 : return;
3975 :
3976 0 : for (i = 0; i < VIF_FAT_FLOW_NUM_BITMAPS; i++) {
3977 0 : if (mem[i]) {
3978 0 : vr_free(mem[i], VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3979 0 : mem[i] = NULL;
3980 : }
3981 : }
3982 :
3983 0 : vr_free(mem, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
3984 0 : return;
3985 : }
3986 :
3987 : static int
3988 0 : __vif_fat_flow_add_no_prefix_rule(uint8_t **no_prefix_rules[VIF_FAT_FLOW_MAXPROTO_INDEX],
3989 : uint8_t proto, uint16_t port, uint8_t port_data)
3990 : {
3991 0 : uint8_t port_val = VIF_FAT_FLOW_PORT_SET;
3992 : unsigned int proto_index, port_row, port_word, port_bit;
3993 :
3994 0 : bool alloced = false;
3995 :
3996 0 : proto_index = vif_fat_flow_get_proto_index(proto);
3997 :
3998 0 : if (!no_prefix_rules[proto_index]) {
3999 0 : no_prefix_rules[proto_index] =
4000 0 : vr_zalloc(VIF_FAT_FLOW_NUM_BITMAPS * sizeof(unsigned int *),
4001 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4002 0 : if (!no_prefix_rules[proto_index])
4003 0 : return -ENOMEM;
4004 0 : alloced = true;
4005 : }
4006 :
4007 0 : port_row = port / VIF_FAT_FLOW_PORTS_PER_BITMAP;
4008 0 : port_word = ((port % VIF_FAT_FLOW_PORTS_PER_BITMAP) * 2) / (sizeof(uint8_t) * 8);
4009 0 : port_bit = ((port % VIF_FAT_FLOW_PORTS_PER_BITMAP) * 2) % (sizeof(uint8_t) * 8);
4010 :
4011 0 : if (!no_prefix_rules[proto_index][port_row]) {
4012 0 : no_prefix_rules[proto_index][port_row] =
4013 0 : vr_zalloc(VIF_FAT_FLOW_BITMAP_BYTES,
4014 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4015 0 : if (!no_prefix_rules[proto_index][port_row]) {
4016 0 : if (alloced) {
4017 0 : vr_free(no_prefix_rules[proto_index],
4018 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4019 0 : no_prefix_rules[proto_index] = NULL;
4020 0 : return -ENOMEM;
4021 : }
4022 : }
4023 : }
4024 :
4025 0 : if ((port_data == VIF_FAT_FLOW_PORT_SIP_IGNORE) ||
4026 : (port_data == VIF_FAT_FLOW_PORT_DIP_IGNORE))
4027 0 : port_val = port_data;
4028 :
4029 : /* First reset the old value */
4030 0 : no_prefix_rules[proto_index][port_row][port_word] &=
4031 0 : ~(VIF_FAT_FLOW_DATA_MASK << port_bit);
4032 :
4033 : /* Set the new val*/
4034 0 : no_prefix_rules[proto_index][port_row][port_word] |=
4035 0 : (port_val << port_bit);
4036 :
4037 0 : return 0;
4038 : }
4039 :
4040 : static int
4041 0 : __vif_is_fat_flow_src_prefix_rule(vr_fat_flow_cfg_t *cfg)
4042 : {
4043 0 : switch (VIF_FAT_FLOW_CFG_PREFIX_AGGR_DATA(cfg->port_aggr_info)) {
4044 0 : case VR_AGGREGATE_SRC_IPV4:
4045 : case VR_AGGREGATE_SRC_IPV6:
4046 0 : return 1;
4047 0 : default:
4048 0 : return 0;
4049 : }
4050 : return 0;
4051 : }
4052 :
4053 : static int
4054 0 : __vif_is_fat_flow_dst_prefix_rule(vr_fat_flow_cfg_t *cfg)
4055 : {
4056 0 : switch (VIF_FAT_FLOW_CFG_PREFIX_AGGR_DATA(cfg->port_aggr_info)) {
4057 0 : case VR_AGGREGATE_DST_IPV4:
4058 : case VR_AGGREGATE_DST_IPV6:
4059 0 : return 1;
4060 0 : default:
4061 0 : return 0;
4062 : }
4063 : return 0;
4064 : }
4065 :
4066 : static int
4067 0 : __vif_is_fat_flow_src_dst_prefix_rule(vr_fat_flow_cfg_t *cfg)
4068 : {
4069 0 : switch (VIF_FAT_FLOW_CFG_PREFIX_AGGR_DATA(cfg->port_aggr_info)) {
4070 0 : case VR_AGGREGATE_SRC_DST_IPV4:
4071 : case VR_AGGREGATE_SRC_DST_IPV6:
4072 0 : return 1;
4073 0 : default:
4074 0 : return 0;
4075 : }
4076 : return 0;
4077 : }
4078 :
4079 : static int
4080 0 : __vif_is_fat_flow_v4_prefix_rule(vr_fat_flow_cfg_t *cfg)
4081 : {
4082 0 : switch (VIF_FAT_FLOW_CFG_PREFIX_AGGR_DATA(cfg->port_aggr_info)) {
4083 0 : case VR_AGGREGATE_SRC_IPV4:
4084 : case VR_AGGREGATE_DST_IPV4:
4085 : case VR_AGGREGATE_SRC_DST_IPV4:
4086 0 : return 1;
4087 0 : default:
4088 0 : return 0;
4089 : }
4090 : return 0;
4091 : }
4092 :
4093 :
4094 : static int
4095 349 : vif_fat_flow_cfg_is_changed(struct vr_interface *vif, vr_interface_req *req)
4096 : {
4097 : int i;
4098 : vr_fat_flow_cfg_t new_cfg;
4099 :
4100 349 : if (vif->fat_flow_cfg_size != req->vifr_fat_flow_protocol_port_size) {
4101 0 : return 1;
4102 : }
4103 349 : for (i = 0; i < vif->fat_flow_cfg_size; i++) {
4104 0 : new_cfg.protocol =
4105 0 : VIF_FAT_FLOW_PROTOCOL(req->vifr_fat_flow_protocol_port[i]);
4106 0 : new_cfg.port =
4107 0 : VIF_FAT_FLOW_PORT(req->vifr_fat_flow_protocol_port[i]);
4108 0 : new_cfg.port_aggr_info =
4109 0 : VIF_FAT_FLOW_PORT_AGGR_INFO(req->vifr_fat_flow_protocol_port[i]);
4110 0 : new_cfg.src_prefix_h = req->vifr_fat_flow_src_prefix_h[i];
4111 0 : new_cfg.src_prefix_l = req->vifr_fat_flow_src_prefix_l[i];
4112 0 : new_cfg.src_prefix_mask = req->vifr_fat_flow_src_prefix_mask[i];
4113 0 : new_cfg.src_aggregate_plen = req->vifr_fat_flow_src_aggregate_plen[i];
4114 0 : new_cfg.dst_prefix_h = req->vifr_fat_flow_dst_prefix_h[i];
4115 0 : new_cfg.dst_prefix_l = req->vifr_fat_flow_dst_prefix_l[i];
4116 0 : new_cfg.dst_prefix_mask = req->vifr_fat_flow_dst_prefix_mask[i];
4117 0 : new_cfg.dst_aggregate_plen = req->vifr_fat_flow_dst_aggregate_plen[i];
4118 0 : if (memcmp(&new_cfg, &vif->fat_flow_cfg[i], sizeof(vr_fat_flow_cfg_t)) != 0) {
4119 0 : return 1;
4120 : }
4121 : }
4122 349 : return 0;
4123 : }
4124 :
4125 : static int
4126 0 : vif_fat_flow_cfg_build(vr_interface_req *req,
4127 : vr_fat_flow_cfg_t **new_fat_flow_cfg,
4128 : uint16_t *new_fat_flow_cfg_size,
4129 : uint16_t *new_fat_flow_num_rules)
4130 : {
4131 : vr_fat_flow_cfg_t cfg;
4132 : int i;
4133 :
4134 : /* If there is no new cfg, return */
4135 0 : if (!req->vifr_fat_flow_protocol_port_size) {
4136 0 : *new_fat_flow_cfg = NULL;
4137 0 : *new_fat_flow_cfg_size = 0;
4138 0 : return 0;
4139 : }
4140 :
4141 0 : *new_fat_flow_cfg = vr_zalloc(sizeof(vr_fat_flow_cfg_t) *
4142 0 : req->vifr_fat_flow_protocol_port_size,
4143 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4144 0 : if (!(*new_fat_flow_cfg)) {
4145 0 : return -ENOMEM;
4146 : }
4147 0 : *new_fat_flow_cfg_size = req->vifr_fat_flow_protocol_port_size;
4148 0 : for (i = 0; i < req->vifr_fat_flow_protocol_port_size; i++) {
4149 0 : cfg.protocol =
4150 0 : VIF_FAT_FLOW_PROTOCOL(req->vifr_fat_flow_protocol_port[i]);
4151 0 : cfg.port =
4152 0 : VIF_FAT_FLOW_PORT(req->vifr_fat_flow_protocol_port[i]);
4153 0 : cfg.port_aggr_info =
4154 0 : VIF_FAT_FLOW_PORT_AGGR_INFO(req->vifr_fat_flow_protocol_port[i]);
4155 0 : cfg.src_prefix_h = req->vifr_fat_flow_src_prefix_h[i];
4156 0 : cfg.src_prefix_l = req->vifr_fat_flow_src_prefix_l[i];
4157 0 : cfg.src_prefix_mask = req->vifr_fat_flow_src_prefix_mask[i];
4158 0 : cfg.src_aggregate_plen = req->vifr_fat_flow_src_aggregate_plen[i];
4159 0 : cfg.dst_prefix_h = req->vifr_fat_flow_dst_prefix_h[i];
4160 0 : cfg.dst_prefix_l = req->vifr_fat_flow_dst_prefix_l[i];
4161 0 : cfg.dst_prefix_mask = req->vifr_fat_flow_dst_prefix_mask[i];
4162 0 : cfg.dst_aggregate_plen = req->vifr_fat_flow_dst_aggregate_plen[i];
4163 0 : (*new_fat_flow_cfg)[i] = cfg;
4164 0 : new_fat_flow_num_rules[vif_fat_flow_get_proto_index(cfg.protocol)]++;
4165 : }
4166 0 : return 0;
4167 : }
4168 :
4169 : static void
4170 0 : vif_fat_flow_cfg_swap(struct vr_interface *vif,
4171 : vr_fat_flow_cfg_t *new_fat_flow_cfg,
4172 : uint16_t new_fat_flow_cfg_size,
4173 : uint16_t *new_fat_flow_num_rules,
4174 : vr_fat_flow_cfg_t **old_fat_flow_cfg)
4175 : {
4176 0 : *old_fat_flow_cfg = vif->fat_flow_cfg;
4177 0 : vif->fat_flow_cfg = new_fat_flow_cfg;
4178 0 : vif->fat_flow_cfg_size = new_fat_flow_cfg_size;
4179 0 : memcpy(vif->fat_flow_num_rules, new_fat_flow_num_rules,
4180 : sizeof(vif->fat_flow_num_rules));
4181 0 : }
4182 :
4183 : static void
4184 0 : vif_fat_flow_cfg_free(vr_fat_flow_cfg_t *old_fat_flow_cfg)
4185 : {
4186 0 : if (old_fat_flow_cfg) {
4187 0 : vr_free(old_fat_flow_cfg, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4188 : }
4189 0 : }
4190 :
4191 : /*
4192 : * Function to allocate a prefix rule data structure;
4193 : *
4194 : * Some notes on the design:
4195 : * All the prefix based fat flow rules are stored in mtries based
4196 : * on the ip address type & prefix type
4197 : * A prefix based fat flow rule can be of 3 types:-
4198 : * 1) Fat flow rule with only src prefix
4199 : * 2) Fat flow rule with only dst prefix
4200 : * 3) Fat flow rule with both src and dst prefix
4201 : * The src and src+dst based rules are store in the src_prefix mtrie
4202 : * whereas the dst based rule is stored in the dst_prefix mtrie;
4203 : * The 3 types of rules are represented as below -
4204 : * src prefix rule
4205 : * src_prefix -> rule_data -> proto_info[proto] -> port_itable -> port_data
4206 : * dst prefix rule
4207 : * dst_prefix -> rule_data -> proto_info[proto] -> port_itable -> port_data
4208 : * src+ dst prefix rule
4209 : * src_prefix -> rule_data -> proto_info[proto] \
4210 : * -> port_itable -> port_data -> dst_prefix
4211 : */
4212 : static vr_fat_flow_prefix_rule_data_t *
4213 0 : __vif_fat_flow_alloc_prefix_rule_data(vr_fat_flow_cfg_t *cfg)
4214 : {
4215 0 : vr_fat_flow_prefix_rule_data_t *rdata = NULL;
4216 : int i, proto_index;
4217 0 : vr_itable_t ptable = NULL;
4218 0 : vr_fat_flow_prefix_rule_port_data_t *port_data = NULL;
4219 : struct vr_route_req vr_req;
4220 : uint64_t prefix[2];
4221 : int ret;
4222 :
4223 : /* Allocate the rule and fill in the rule details */
4224 0 : rdata = vr_zalloc(sizeof(vr_fat_flow_prefix_rule_data_t),
4225 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4226 0 : if (!rdata) {
4227 0 : goto err;
4228 : }
4229 0 : rdata->proto_info = vr_zalloc(sizeof(vr_fat_flow_prefix_rule_proto_info_t),
4230 : VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4231 0 : if (!rdata->proto_info) {
4232 0 : goto err;
4233 : }
4234 0 : for (i = 0; i < VIF_FAT_FLOW_MAXPROTO_INDEX; i++) {
4235 0 : rdata->proto_info->proto[i] = NULL;
4236 : }
4237 0 : rdata->next = NULL;
4238 0 : proto_index = vif_fat_flow_get_proto_index(cfg->protocol);
4239 0 : ptable = vr_itable_create(16, 2, 8, 8);
4240 0 : if (!ptable) {
4241 0 : goto err;
4242 : }
4243 0 : rdata->proto_info->proto[proto_index] = ptable;
4244 :
4245 0 : port_data = vr_zalloc(sizeof(*port_data), VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4246 0 : if (!port_data) {
4247 0 : goto err;
4248 : }
4249 0 : port_data->second_prefix = NULL;
4250 : /* Add the port data to itable */
4251 0 : if (vr_itable_set(ptable, cfg->port, (void *)port_data) == VR_ITABLE_ERR_PTR) {
4252 0 : vr_printf("%s: Failed to add to itable port %d port_data %p\n",
4253 0 : __FUNCTION__, cfg->port, port_data);
4254 0 : goto err;
4255 : }
4256 :
4257 0 : if (__vif_is_fat_flow_src_dst_prefix_rule(cfg)) {
4258 0 : port_data->rule_type = PREFIX_RULE_TYPE_DUAL_PREFIX;
4259 : } else {
4260 0 : port_data->rule_type = PREFIX_RULE_TYPE_SINGLE_PREFIX;
4261 0 : if (VIF_FAT_FLOW_CFG_PORT_DATA(cfg->port_aggr_info) ==
4262 : VIF_FAT_FLOW_PORT_SIP_IGNORE) {
4263 0 : port_data->rule_type |= PREFIX_RULE_HAS_IGNORE_SRC;
4264 0 : } else if (VIF_FAT_FLOW_CFG_PORT_DATA(cfg->port_aggr_info) ==
4265 : VIF_FAT_FLOW_PORT_DIP_IGNORE) {
4266 0 : port_data->rule_type |= PREFIX_RULE_HAS_IGNORE_DST;
4267 : }
4268 : }
4269 0 : if (__vif_is_fat_flow_dst_prefix_rule(cfg)) {
4270 0 : port_data->aggr_plen = cfg->dst_aggregate_plen;
4271 : } else {
4272 0 : port_data->aggr_plen = cfg->src_aggregate_plen;
4273 : }
4274 : /* Insert the dst/second prefix also into the rule */
4275 0 : if (__vif_is_fat_flow_src_dst_prefix_rule(cfg)) {
4276 0 : port_data->second_prefix = vdata_mtrie_init(0, &dummy_plen);
4277 0 : if (!port_data->second_prefix) {
4278 0 : goto err;
4279 : }
4280 0 : memset(&vr_req, 0, sizeof(vr_route_req));
4281 0 : if (__vif_is_fat_flow_v4_prefix_rule(cfg)) {
4282 0 : vr_req.rtr_req.rtr_family = AF_INET;
4283 0 : vr_req.rtr_req.rtr_prefix_size = 4;
4284 0 : prefix[0] = cfg->dst_prefix_l;
4285 0 : prefix[1] = cfg->dst_prefix_h;
4286 : } else {
4287 0 : vr_req.rtr_req.rtr_family = AF_INET6;
4288 0 : vr_req.rtr_req.rtr_prefix_size = 16;
4289 0 : prefix[0] = cfg->dst_prefix_h;
4290 0 : prefix[1] = cfg->dst_prefix_l;
4291 : }
4292 0 : vr_req.rtr_req.rtr_prefix = (int8_t *) prefix;
4293 0 : vr_req.rtr_req.rtr_prefix_len = cfg->dst_prefix_mask;
4294 0 : vr_req.rtr_nh = (struct vr_nexthop *) (size_t) cfg->dst_aggregate_plen;
4295 : /* Add the prefix into mtrie */
4296 0 : ret = vdata_mtrie_add(port_data->second_prefix, &vr_req);
4297 0 : if (ret != 0) {
4298 0 : goto err;
4299 : }
4300 : }
4301 0 : return rdata;
4302 :
4303 0 : err:
4304 0 : if (port_data) {
4305 0 : if (port_data->second_prefix) {
4306 0 : vdata_mtrie_delete_all(port_data->second_prefix);
4307 : }
4308 0 : vr_free(port_data, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4309 : }
4310 0 : if (ptable) {
4311 0 : vr_itable_delete(ptable, NULL);
4312 : }
4313 0 : if (rdata) {
4314 0 : if (rdata->proto_info) {
4315 0 : vr_free(rdata->proto_info, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4316 : }
4317 0 : vr_free(rdata, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4318 : }
4319 0 : return NULL;
4320 : }
4321 :
4322 :
4323 : static int
4324 0 : __vif_fat_flow_update_prefix_rule_data(vr_fat_flow_prefix_rule_data_t *rdata,
4325 : vr_fat_flow_cfg_t *cfg)
4326 : {
4327 : int proto_index;
4328 : vr_itable_t ptable;
4329 : vr_fat_flow_prefix_rule_port_data_t *port_data;
4330 : struct vr_route_req vr_req;
4331 : uint64_t prefix[2];
4332 : int ret;
4333 :
4334 : /* Lookup the protocol */
4335 0 : proto_index = vif_fat_flow_get_proto_index(cfg->protocol);
4336 0 : ptable = rdata->proto_info->proto[proto_index];
4337 0 : if (!ptable) {
4338 0 : ptable = vr_itable_create(16, 2, 8, 8);
4339 0 : if (!ptable) {
4340 0 : return -1;
4341 : }
4342 0 : rdata->proto_info->proto[proto_index] = ptable;
4343 : }
4344 : /* Lookup the port */
4345 0 : port_data = (vr_fat_flow_prefix_rule_port_data_t *) vr_itable_get(ptable, cfg->port);
4346 0 : if (!port_data) {
4347 0 : port_data = vr_zalloc(sizeof(*port_data), VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4348 0 : if (!port_data) {
4349 0 : return -1;
4350 : }
4351 : /* Add the port data to itable */
4352 0 : vr_itable_set(ptable, cfg->port, (void *)port_data);
4353 : }
4354 :
4355 : /* Update port data */
4356 0 : if (__vif_is_fat_flow_src_dst_prefix_rule(cfg)) {
4357 0 : port_data->rule_type |= PREFIX_RULE_TYPE_DUAL_PREFIX;
4358 : } else {
4359 0 : port_data->rule_type |= PREFIX_RULE_TYPE_SINGLE_PREFIX;
4360 0 : if (VIF_FAT_FLOW_CFG_PORT_DATA(cfg->port_aggr_info) ==
4361 : VIF_FAT_FLOW_PORT_SIP_IGNORE) {
4362 0 : port_data->rule_type |= PREFIX_RULE_HAS_IGNORE_SRC;
4363 0 : } else if (VIF_FAT_FLOW_CFG_PORT_DATA(cfg->port_aggr_info) ==
4364 : VIF_FAT_FLOW_PORT_DIP_IGNORE) {
4365 0 : port_data->rule_type |= PREFIX_RULE_HAS_IGNORE_DST;
4366 : }
4367 : }
4368 0 : if (__vif_is_fat_flow_dst_prefix_rule(cfg)) {
4369 0 : port_data->aggr_plen = cfg->dst_aggregate_plen;
4370 : } else {
4371 0 : port_data->aggr_plen = cfg->src_aggregate_plen;
4372 : }
4373 : /* Insert the dst/second prefix also into the rule */
4374 0 : if (__vif_is_fat_flow_src_dst_prefix_rule(cfg)) {
4375 0 : if (!port_data->second_prefix) {
4376 0 : port_data->second_prefix = vdata_mtrie_init(0, &dummy_plen);
4377 0 : if (!port_data->second_prefix) {
4378 0 : return -1;
4379 : }
4380 : }
4381 0 : memset(&vr_req, 0, sizeof(vr_route_req));
4382 0 : if (__vif_is_fat_flow_v4_prefix_rule(cfg)) {
4383 0 : vr_req.rtr_req.rtr_family = AF_INET;
4384 0 : vr_req.rtr_req.rtr_prefix_size = 4;
4385 0 : prefix[0] = cfg->dst_prefix_l;
4386 0 : prefix[1] = cfg->dst_prefix_h;
4387 : } else {
4388 0 : vr_req.rtr_req.rtr_family = AF_INET6;
4389 0 : vr_req.rtr_req.rtr_prefix_size = 16;
4390 0 : prefix[0] = cfg->dst_prefix_h;
4391 0 : prefix[1] = cfg->dst_prefix_l;
4392 : }
4393 0 : vr_req.rtr_req.rtr_prefix = (int8_t *)prefix;
4394 0 : vr_req.rtr_req.rtr_prefix_len = cfg->dst_prefix_mask;
4395 0 : vr_req.rtr_nh = (struct vr_nexthop *) (size_t) cfg->dst_aggregate_plen;
4396 : /* Add the prefix into mtrie */
4397 0 : ret = vdata_mtrie_add(port_data->second_prefix, &vr_req);
4398 0 : if (ret != 0) {
4399 0 : return -1;
4400 : }
4401 : }
4402 :
4403 0 : return 0;
4404 : }
4405 :
4406 : static int
4407 0 : __vif_fat_flow_add_prefix_rule(struct ip_mtrie *rules, vr_fat_flow_cfg_t *cfg,
4408 : vr_fat_flow_prefix_rule_data_t **rule_data)
4409 : {
4410 : struct vr_route_req vr_req, add_req;
4411 : uint64_t prefix[2];
4412 0 : vr_fat_flow_prefix_rule_data_t *rdata = NULL;
4413 : int ret, prefix_len;
4414 :
4415 : /* Check if the src/dst prefix already exists */
4416 0 : memset(&vr_req, 0, sizeof(vr_route_req));
4417 0 : memset(&add_req, 0, sizeof(vr_route_req));
4418 :
4419 0 : if (__vif_is_fat_flow_v4_prefix_rule(cfg)) {
4420 0 : vr_req.rtr_req.rtr_family = AF_INET;
4421 0 : vr_req.rtr_req.rtr_prefix_size = 4;
4422 : } else {
4423 0 : vr_req.rtr_req.rtr_family = AF_INET6;
4424 0 : vr_req.rtr_req.rtr_prefix_size = 16;
4425 : }
4426 0 : if (__vif_is_fat_flow_src_prefix_rule(cfg) ||
4427 0 : __vif_is_fat_flow_src_dst_prefix_rule(cfg)) {
4428 0 : if (__vif_is_fat_flow_v4_prefix_rule(cfg)) {
4429 0 : prefix[0] = cfg->src_prefix_l;
4430 0 : prefix[1] = cfg->src_prefix_h;
4431 : } else {
4432 : /* for v6 it is other way round */
4433 0 : prefix[0] = cfg->src_prefix_h;
4434 0 : prefix[1] = cfg->src_prefix_l;
4435 : }
4436 0 : vr_req.rtr_req.rtr_prefix_len = cfg->src_prefix_mask;
4437 : } else {
4438 0 : if (__vif_is_fat_flow_v4_prefix_rule(cfg)) {
4439 0 : prefix[0] = cfg->dst_prefix_l;
4440 0 : prefix[1] = cfg->dst_prefix_h;
4441 : } else {
4442 0 : prefix[0] = cfg->dst_prefix_h;
4443 0 : prefix[1] = cfg->dst_prefix_l;
4444 : }
4445 0 : vr_req.rtr_req.rtr_prefix_len = cfg->dst_prefix_mask;
4446 : }
4447 0 : prefix_len = vr_req.rtr_req.rtr_prefix_len;
4448 0 : vr_req.rtr_req.rtr_prefix = (int8_t *)prefix;
4449 0 : add_req = vr_req;
4450 :
4451 0 : rdata = vdata_mtrie_lookup(rules, &vr_req);
4452 :
4453 : /* This is a new prefix */
4454 0 : if (!rdata || (prefix_len != vr_req.rtr_req.rtr_prefix_len)) {
4455 0 : rdata = __vif_fat_flow_alloc_prefix_rule_data(cfg);
4456 0 : if (!rdata) {
4457 0 : return -1;
4458 : }
4459 : /* Add the rule data to the list */
4460 0 : if (*rule_data) {
4461 0 : rdata->next = *rule_data;
4462 : }
4463 0 : *rule_data = rdata;
4464 0 : add_req.rtr_nh = (struct vr_nexthop *) rdata;
4465 : /* Add the prefix into mtrie */
4466 0 : ret = vdata_mtrie_add(rules, &add_req);
4467 0 : if (ret != 0) {
4468 0 : return ret;
4469 : }
4470 : } else {
4471 : /* Update the existing prefix's rule data */
4472 0 : ret = __vif_fat_flow_update_prefix_rule_data(rdata, cfg);
4473 0 : if (ret != 0) {
4474 0 : return ret;
4475 : }
4476 : }
4477 0 : return 0;
4478 : }
4479 :
4480 : static void
4481 0 : __vif_flat_flow_free_no_prefix_rules_cb(struct vrouter *router, void *data)
4482 : {
4483 0 : struct vr_defer_data *vdd = (struct vr_defer_data *)data;
4484 0 : uint8_t **no_prefix_rules = NULL;
4485 :
4486 0 : if (!vdd || !vdd->vdd_data)
4487 0 : return;
4488 0 : no_prefix_rules = (uint8_t **) vdd->vdd_data;
4489 :
4490 0 : if (no_prefix_rules) {
4491 0 : vif_fat_flow_free(no_prefix_rules);
4492 : }
4493 : }
4494 :
4495 : static void
4496 0 : __vif_fat_flow_delete_all_no_prefix_rules(
4497 : uint8_t **no_prefix_rules[VIF_FAT_FLOW_MAXPROTO_INDEX])
4498 : {
4499 : struct vr_defer_data *vdd_npr;
4500 : int i;
4501 :
4502 0 : for (i = 0; i < VIF_FAT_FLOW_MAXPROTO_INDEX; i++) {
4503 0 : vdd_npr = vr_get_defer_data(sizeof(*vdd_npr));
4504 0 : if (!vdd_npr)
4505 0 : return;
4506 0 : vdd_npr->vdd_data = (void *) no_prefix_rules[i];
4507 0 : vr_defer(vrouter_get(0), __vif_flat_flow_free_no_prefix_rules_cb, vdd_npr);
4508 : }
4509 : }
4510 :
4511 : static void
4512 0 : __vif_flat_flow_free_prefix_rules_cb(struct vrouter *router, void *data)
4513 : {
4514 : struct ip_mtrie *prefix_rules;
4515 0 : struct vr_defer_data *vdd = (struct vr_defer_data *)data;
4516 :
4517 0 : if (!vdd || !vdd->vdd_data)
4518 0 : return;
4519 0 : prefix_rules = (struct ip_mtrie *) vdd->vdd_data;
4520 0 : vdata_mtrie_delete_all(prefix_rules);
4521 : }
4522 :
4523 : static void
4524 0 : __vif_fat_flow_delete_all_prefix_rules(struct ip_mtrie *prefix_rules)
4525 : {
4526 : struct vr_defer_data *vdd_pr;
4527 :
4528 0 : vdd_pr = vr_get_defer_data(sizeof(*vdd_pr));
4529 0 : if (!vdd_pr)
4530 0 : return;
4531 0 : vdd_pr->vdd_data = (void *) prefix_rules;
4532 0 : vr_defer(vrouter_get(0), __vif_flat_flow_free_prefix_rules_cb, vdd_pr);
4533 : }
4534 :
4535 : static void
4536 0 : __vif_fat_flow_free_port_data_cb(unsigned int index, void *data)
4537 : {
4538 : vr_fat_flow_prefix_rule_port_data_t *port_data;
4539 0 : if (!data) {
4540 0 : return;
4541 : }
4542 0 : port_data = (vr_fat_flow_prefix_rule_port_data_t *) data;
4543 0 : if (port_data->second_prefix) {
4544 0 : vdata_mtrie_delete_all(port_data->second_prefix);
4545 : }
4546 0 : vr_free(port_data, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4547 : }
4548 :
4549 : static void
4550 0 : __vif_fat_flow_free_all_rule_data_list(vr_fat_flow_prefix_rule_data_t *head)
4551 : {
4552 : vr_fat_flow_prefix_rule_data_t *nextent;
4553 : int i;
4554 :
4555 0 : while (head) {
4556 0 : nextent = head->next;
4557 :
4558 0 : for (i = 0; i < VIF_FAT_FLOW_MAXPROTO_INDEX; i++) {
4559 0 : if (!head->proto_info->proto[i])
4560 0 : continue;
4561 0 : vr_itable_delete(head->proto_info->proto[i],
4562 : __vif_fat_flow_free_port_data_cb);
4563 : }
4564 0 : vr_free(head->proto_info, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4565 0 : vr_free(head, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4566 :
4567 0 : head = nextent;
4568 : }
4569 0 : }
4570 :
4571 : static void
4572 0 : __vif_fat_flow_free_rule_data_defer_cb(struct vrouter *router, void *data)
4573 : {
4574 0 : struct vr_defer_data *vdd = (struct vr_defer_data *)data;
4575 : vr_fat_flow_prefix_rule_data_t *rdata;
4576 : int i;
4577 :
4578 0 : if (!vdd || !vdd->vdd_data)
4579 0 : return;
4580 :
4581 0 : rdata = (vr_fat_flow_prefix_rule_data_t *) vdd->vdd_data;
4582 0 : for (i = 0; i < VIF_FAT_FLOW_MAXPROTO_INDEX; i++) {
4583 0 : if (!rdata->proto_info->proto[i])
4584 0 : continue;
4585 0 : vr_itable_delete(rdata->proto_info->proto[i],
4586 : __vif_fat_flow_free_port_data_cb);
4587 : }
4588 0 : vr_free(rdata->proto_info, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4589 0 : vr_free(rdata, VR_INTERFACE_FAT_FLOW_CONFIG_OBJECT);
4590 0 : return;
4591 : }
4592 :
4593 : static void
4594 0 : __vif_fat_flow_delete_all_rule_data_list(vr_fat_flow_prefix_rule_data_t *head)
4595 : {
4596 : vr_fat_flow_prefix_rule_data_t *nextent;
4597 : struct vr_defer_data *vdd_rd;
4598 :
4599 0 : while (head) {
4600 0 : nextent = head->next;
4601 0 : vdd_rd = vr_get_defer_data(sizeof(*vdd_rd));
4602 0 : if (!vdd_rd)
4603 0 : return;
4604 0 : vdd_rd->vdd_data = (void *) head;
4605 0 : vr_defer(vrouter_get(0), __vif_fat_flow_free_rule_data_defer_cb, vdd_rd);
4606 0 : head = nextent;
4607 : }
4608 : }
4609 :
4610 : static int
4611 0 : vif_fat_flow_rules_build(vr_fat_flow_cfg_t *new_cfg, uint16_t new_cfg_size,
4612 : struct vr_interface *vif)
4613 : {
4614 0 : uint8_t **no_prefix_rules[VIF_FAT_FLOW_MAXPROTO_INDEX] = {NULL},
4615 0 : **old_no_prefix_rules[VIF_FAT_FLOW_MAXPROTO_INDEX] = {NULL};
4616 0 : struct ip_mtrie *v4_src_prefix_rules = NULL,
4617 0 : *old_v4_src_prefix_rules = NULL;
4618 0 : struct ip_mtrie *v4_dst_prefix_rules = NULL,
4619 0 : *old_v4_dst_prefix_rules = NULL;
4620 0 : struct ip_mtrie *v6_src_prefix_rules = NULL,
4621 0 : *old_v6_src_prefix_rules = NULL;
4622 0 : struct ip_mtrie *v6_dst_prefix_rules = NULL,
4623 0 : *old_v6_dst_prefix_rules = NULL;
4624 0 : struct ip_mtrie **prefix_rules = NULL;
4625 0 : vr_fat_flow_prefix_rule_data_t *rule_data_list = NULL,
4626 0 : *old_rule_data_list = NULL;
4627 : uint8_t prefix_aggr;
4628 : uint8_t proto, proto_index, port_data;
4629 : uint16_t port;
4630 0 : int i, ret = 0;
4631 :
4632 0 : for (i = 0; i < new_cfg_size; i++) {
4633 0 : prefix_aggr = VIF_FAT_FLOW_CFG_PREFIX_AGGR_DATA(new_cfg[i].port_aggr_info);
4634 0 : switch (prefix_aggr) {
4635 0 : case VR_AGGREGATE_NONE:
4636 0 : proto = new_cfg[i].protocol;
4637 0 : port = new_cfg[i].port;
4638 0 : proto_index = vif_fat_flow_get_proto_index(proto);
4639 0 : port_data = VIF_FAT_FLOW_CFG_PORT_DATA(new_cfg[i].port_aggr_info);
4640 0 : if (proto_index == VIF_FAT_FLOW_NOPROTO_INDEX)
4641 0 : port = proto;
4642 0 : ret = __vif_fat_flow_add_no_prefix_rule(no_prefix_rules,
4643 : proto, port, port_data);
4644 0 : if (ret) {
4645 0 : goto err;
4646 : }
4647 0 : break;
4648 0 : case VR_AGGREGATE_SRC_IPV4:
4649 : case VR_AGGREGATE_SRC_IPV6:
4650 : case VR_AGGREGATE_DST_IPV4:
4651 : case VR_AGGREGATE_DST_IPV6:
4652 : case VR_AGGREGATE_SRC_DST_IPV4:
4653 : case VR_AGGREGATE_SRC_DST_IPV6:
4654 0 : if ((prefix_aggr == VR_AGGREGATE_SRC_IPV4) ||
4655 : (prefix_aggr == VR_AGGREGATE_SRC_DST_IPV4)) {
4656 0 : prefix_rules = &v4_src_prefix_rules;
4657 0 : } else if ((prefix_aggr == VR_AGGREGATE_SRC_IPV6) ||
4658 : (prefix_aggr == VR_AGGREGATE_SRC_DST_IPV6)) {
4659 0 : prefix_rules = &v6_src_prefix_rules;
4660 0 : } else if (prefix_aggr == VR_AGGREGATE_DST_IPV4) {
4661 0 : prefix_rules = &v4_dst_prefix_rules;
4662 : } else {
4663 0 : prefix_rules = &v6_dst_prefix_rules;
4664 : }
4665 0 : if (!(*prefix_rules)) {
4666 0 : *prefix_rules = vdata_mtrie_init(0, &dummy_rule);
4667 0 : if (!(*prefix_rules)) {
4668 0 : ret = -ENOMEM;
4669 0 : goto err;
4670 : }
4671 : }
4672 0 : ret = __vif_fat_flow_add_prefix_rule((*prefix_rules),
4673 0 : &new_cfg[i], &rule_data_list);
4674 0 : if (ret != 0) {
4675 0 : goto err;
4676 : }
4677 0 : break;
4678 0 : default:
4679 0 : break;
4680 : }
4681 : }
4682 : /* Save the old rules */
4683 0 : for (i = 0; i < VIF_FAT_FLOW_MAXPROTO_INDEX; i++) {
4684 0 : old_no_prefix_rules[i] = vif->vif_fat_flow_no_prefix_rules[i];
4685 : }
4686 0 : old_v4_src_prefix_rules = vif->vif_fat_flow_v4_src_prefix_rules;
4687 0 : old_v4_dst_prefix_rules = vif->vif_fat_flow_v4_dst_prefix_rules;
4688 0 : old_v6_src_prefix_rules = vif->vif_fat_flow_v6_src_prefix_rules;
4689 0 : old_v6_dst_prefix_rules = vif->vif_fat_flow_v6_dst_prefix_rules;
4690 0 : old_rule_data_list = vif->vif_fat_flow_rule_data_list;
4691 :
4692 : /* Copy the new rules to vif */
4693 0 : for (i = 0; i < VIF_FAT_FLOW_MAXPROTO_INDEX; i++) {
4694 0 : vif->vif_fat_flow_no_prefix_rules[i] = no_prefix_rules[i];
4695 : }
4696 0 : vif->vif_fat_flow_v4_src_prefix_rules = v4_src_prefix_rules;
4697 0 : vif->vif_fat_flow_v4_dst_prefix_rules = v4_dst_prefix_rules;
4698 0 : vif->vif_fat_flow_v6_src_prefix_rules = v6_src_prefix_rules;
4699 0 : vif->vif_fat_flow_v6_dst_prefix_rules = v6_dst_prefix_rules;
4700 0 : vif->vif_fat_flow_rule_data_list = rule_data_list;
4701 :
4702 : /* Defer delete the old rules */
4703 0 : __vif_fat_flow_delete_all_no_prefix_rules(old_no_prefix_rules);
4704 0 : if (old_v4_src_prefix_rules)
4705 0 : __vif_fat_flow_delete_all_prefix_rules(old_v4_src_prefix_rules);
4706 0 : if (old_v4_dst_prefix_rules)
4707 0 : __vif_fat_flow_delete_all_prefix_rules(old_v4_dst_prefix_rules);
4708 0 : if (old_v6_src_prefix_rules)
4709 0 : __vif_fat_flow_delete_all_prefix_rules(old_v6_src_prefix_rules);
4710 0 : if (old_v6_dst_prefix_rules)
4711 0 : __vif_fat_flow_delete_all_prefix_rules(old_v6_dst_prefix_rules);
4712 0 : if (old_rule_data_list)
4713 0 : __vif_fat_flow_delete_all_rule_data_list(old_rule_data_list);
4714 :
4715 0 : return 0;
4716 :
4717 0 : err:
4718 0 : __vif_fat_flow_delete_all_no_prefix_rules(no_prefix_rules);
4719 0 : if (v4_src_prefix_rules)
4720 0 : __vif_fat_flow_delete_all_prefix_rules(v4_src_prefix_rules);
4721 0 : if (v4_dst_prefix_rules)
4722 0 : __vif_fat_flow_delete_all_prefix_rules(v4_dst_prefix_rules);
4723 0 : if (v6_src_prefix_rules)
4724 0 : __vif_fat_flow_delete_all_prefix_rules(v6_src_prefix_rules);
4725 0 : if (v6_dst_prefix_rules)
4726 0 : __vif_fat_flow_delete_all_prefix_rules(v6_dst_prefix_rules);
4727 0 : if (rule_data_list)
4728 0 : __vif_fat_flow_delete_all_rule_data_list(rule_data_list);
4729 0 : return ret;
4730 : }
4731 :
4732 :
4733 : static int
4734 349 : vif_fat_flow_add(struct vr_interface *vif, vr_interface_req *req)
4735 : {
4736 : int rc;
4737 : vr_fat_flow_cfg_t *old_fat_flow_cfg, *new_fat_flow_cfg;
4738 : uint16_t new_fat_flow_cfg_size;
4739 349 : uint16_t new_fat_flow_num_rules[VIF_FAT_FLOW_MAXPROTO_INDEX] = {0};
4740 :
4741 : int i;
4742 : uint32_t v4_prefix, v4_prefix_len, v4_mask;
4743 : uint64_t v6_prefix_h, v6_prefix_l, v6_mask_l, v6_mask_h;
4744 : uint16_t v6_prefix_len;
4745 :
4746 : /* Populate the ipv4 & ipv6 exclude lists */
4747 349 : if (!req->vifr_fat_flow_exclude_ip_list_size) {
4748 349 : memset(vif->vif_fat_flow_ipv4_exclude_list, 0,
4749 : FAT_FLOW_IPV4_EXCLUDE_LIST_MAX_SIZE * sizeof(uint32_t));
4750 349 : memset(vif->vif_fat_flow_ipv4_exclude_plen_list, 0,
4751 : FAT_FLOW_IPV4_EXCLUDE_LIST_MAX_SIZE * sizeof(uint8_t));
4752 349 : vif->vif_fat_flow_ipv4_exclude_list_size = 0;
4753 : } else {
4754 0 : if (req->vifr_fat_flow_exclude_ip_list_size > FAT_FLOW_IPV4_EXCLUDE_LIST_MAX_SIZE) {
4755 0 : vr_printf("Vrouter: %s:%d vifr_idx: %d vifr_fat_flow_exclude_ip_list_size=%d \n",
4756 : __func__, __LINE__, req->vifr_idx, req->vifr_fat_flow_exclude_ip_list_size);
4757 0 : return -EINVAL;
4758 : }
4759 : /* copy the exclude list and size */
4760 0 : for (i = 0; i < req->vifr_fat_flow_exclude_ip_list_size; i++) {
4761 0 : v4_prefix_len = FAT_FLOW_EXCLUDE_IPV4_PREFIX_LEN(req->vifr_fat_flow_exclude_ip_list[i]);
4762 0 : v4_prefix = FAT_FLOW_EXCLUDE_IPV4_PREFIX(req->vifr_fat_flow_exclude_ip_list[i]);
4763 0 : v4_mask = FAT_FLOW_IPV4_PLEN_TO_MASK(v4_prefix_len);
4764 0 : vif->vif_fat_flow_ipv4_exclude_list[i] = v4_prefix & v4_mask;
4765 0 : vif->vif_fat_flow_ipv4_exclude_plen_list[i] = (uint8_t) v4_prefix_len;
4766 : }
4767 0 : vif->vif_fat_flow_ipv4_exclude_list_size = req->vifr_fat_flow_exclude_ip_list_size;
4768 : }
4769 :
4770 349 : if (!req->vifr_fat_flow_exclude_ip6_l_list_size) {
4771 349 : memset(vif->vif_fat_flow_ipv6_low_exclude_list, 0,
4772 : FAT_FLOW_IPV6_EXCLUDE_LIST_MAX_SIZE * sizeof(uint64_t));
4773 349 : memset(vif->vif_fat_flow_ipv6_high_exclude_list, 0,
4774 : FAT_FLOW_IPV6_EXCLUDE_LIST_MAX_SIZE * sizeof(uint64_t));
4775 349 : memset(vif->vif_fat_flow_ipv6_exclude_plen_list, 0,
4776 : FAT_FLOW_IPV6_EXCLUDE_LIST_MAX_SIZE * sizeof(uint8_t));
4777 349 : vif->vif_fat_flow_ipv6_exclude_list_size = 0;
4778 : } else {
4779 0 : if ((req->vifr_fat_flow_exclude_ip6_l_list_size != req->vifr_fat_flow_exclude_ip6_u_list_size) ||
4780 0 : (req->vifr_fat_flow_exclude_ip6_l_list_size != req->vifr_fat_flow_exclude_ip6_plen_list_size) ||
4781 0 : (req->vifr_fat_flow_exclude_ip6_l_list_size > FAT_FLOW_IPV6_EXCLUDE_LIST_MAX_SIZE)) {
4782 0 : vr_printf("Vrouter: %s:%d vifr_idx: %d vifr_fat_flow_exclude_ip6_l_list_size=%d \n",
4783 : __func__, __LINE__, req->vifr_idx, req->vifr_fat_flow_exclude_ip6_l_list_size);
4784 0 : return -EINVAL;
4785 : }
4786 : /* copy the exclude list and size */
4787 0 : for (i = 0; i < req->vifr_fat_flow_exclude_ip6_l_list_size; i++) {
4788 0 : v6_prefix_l = req->vifr_fat_flow_exclude_ip6_l_list[i];
4789 0 : v6_prefix_h = req->vifr_fat_flow_exclude_ip6_u_list[i];
4790 0 : v6_prefix_len = req->vifr_fat_flow_exclude_ip6_plen_list[i];
4791 0 : fat_flow_ipv6_plen_to_mask(v6_prefix_len, &v6_mask_h, &v6_mask_l);
4792 0 : vif->vif_fat_flow_ipv6_low_exclude_list[i] = v6_prefix_l & v6_mask_l;
4793 0 : vif->vif_fat_flow_ipv6_high_exclude_list[i] = v6_prefix_h & v6_mask_h;
4794 0 : vif->vif_fat_flow_ipv6_exclude_plen_list[i] = (uint8_t) v6_prefix_len;
4795 : }
4796 0 : vif->vif_fat_flow_ipv6_exclude_list_size = req->vifr_fat_flow_exclude_ip6_l_list_size;
4797 : }
4798 :
4799 : /* Do rest of fat flow config processing */
4800 :
4801 : /*
4802 : * Check if fat flow config has changed. If so, then build the new config and rules;
4803 : * Free the old ones.
4804 : */
4805 349 : if (vif_fat_flow_cfg_is_changed(vif, req)) {
4806 : /* Build the new cfg and rules */
4807 0 : rc = vif_fat_flow_cfg_build(req, &new_fat_flow_cfg, &new_fat_flow_cfg_size,
4808 : new_fat_flow_num_rules);
4809 0 : if (rc < 0) {
4810 0 : return rc;
4811 : }
4812 0 : rc = vif_fat_flow_rules_build(new_fat_flow_cfg, new_fat_flow_cfg_size, vif);
4813 0 : if (rc < 0) {
4814 0 : vif_fat_flow_cfg_free(new_fat_flow_cfg);
4815 0 : return rc;
4816 : }
4817 : /* Swap the old cfg with the new one */
4818 0 : vif_fat_flow_cfg_swap(vif, new_fat_flow_cfg, new_fat_flow_cfg_size,
4819 : new_fat_flow_num_rules, &old_fat_flow_cfg);
4820 : /* Free the old cfg */
4821 0 : vif_fat_flow_cfg_free(old_fat_flow_cfg);
4822 : }
4823 :
4824 349 : return 0;
4825 : }
4826 :
4827 : static uint8_t
4828 0 : vif_fat_flow_port_get(struct vr_interface *vif, uint8_t proto_index,
4829 : uint16_t port)
4830 : {
4831 : unsigned int row, column, byte, bit;
4832 :
4833 0 : row = proto_index;
4834 0 : column = port / VIF_FAT_FLOW_PORTS_PER_BITMAP;
4835 :
4836 0 : if (vif->vif_fat_flow_no_prefix_rules[row]) {
4837 0 : if (vif->vif_fat_flow_no_prefix_rules[row][column]) {
4838 0 : byte = ((port % VIF_FAT_FLOW_PORTS_PER_BITMAP) * 2) / 8;
4839 0 : bit = ((port % VIF_FAT_FLOW_PORTS_PER_BITMAP) * 2) % 8;
4840 0 : return (vif->vif_fat_flow_no_prefix_rules[row][column][byte] >> bit) &
4841 : VIF_FAT_FLOW_DATA_MASK;
4842 : }
4843 : }
4844 :
4845 0 : return 0;
4846 : }
4847 :
4848 :
4849 : static uint8_t
4850 57 : vif_fat_flow_exclude_list_lookup (struct vr_interface *vif, unsigned int *saddr, unsigned int *daddr,
4851 : unsigned char *ip6_src, unsigned char *ip6_dst)
4852 : {
4853 : int i;
4854 : uint64_t v6_prefix_h, v6_prefix_l, v6_mask_h, v6_mask_l;
4855 : uint32_t v4_mask;
4856 :
4857 57 : if (saddr) {
4858 53 : if (!vif->vif_fat_flow_ipv4_exclude_list_size) {
4859 53 : return 0;
4860 : }
4861 0 : for (i = 0; i < vif->vif_fat_flow_ipv4_exclude_list_size; i++) {
4862 0 : v4_mask = FAT_FLOW_IPV4_PLEN_TO_MASK(vif->vif_fat_flow_ipv4_exclude_plen_list[i]);
4863 0 : if (((*saddr & v4_mask) == vif->vif_fat_flow_ipv4_exclude_list[i]) ||
4864 0 : ((*daddr & v4_mask) == vif->vif_fat_flow_ipv4_exclude_list[i])) {
4865 0 : return 1;
4866 : }
4867 : }
4868 4 : } else if (ip6_src) {
4869 4 : if (!vif->vif_fat_flow_ipv6_exclude_list_size) {
4870 4 : return 0;
4871 : }
4872 0 : for (i = 0; i < vif->vif_fat_flow_ipv6_exclude_list_size; i++) {
4873 0 : fat_flow_ipv6_plen_to_mask(vif->vif_fat_flow_ipv6_exclude_plen_list[i], &v6_mask_h, &v6_mask_l);
4874 : /* compare src ip */
4875 0 : memcpy(&v6_prefix_h, (uint8_t *) ip6_src, 8);
4876 0 : memcpy(&v6_prefix_l, ((uint8_t *) ip6_src) + 8, 8);
4877 0 : if (((v6_prefix_l & v6_mask_l) == vif->vif_fat_flow_ipv6_low_exclude_list[i]) &&
4878 0 : ((v6_prefix_h & v6_mask_h) == vif->vif_fat_flow_ipv6_high_exclude_list[i])) {
4879 0 : return 1;
4880 : }
4881 : /* compare dst ip */
4882 0 : memcpy(&v6_prefix_h, (uint8_t *) ip6_dst, 8);
4883 0 : memcpy(&v6_prefix_l, ((uint8_t *) ip6_dst) + 8, 8);
4884 0 : if (((v6_prefix_l & v6_mask_l) == vif->vif_fat_flow_ipv6_low_exclude_list[i]) &&
4885 0 : ((v6_prefix_h & v6_mask_h) == vif->vif_fat_flow_ipv6_high_exclude_list[i])) {
4886 0 : return 1;
4887 : }
4888 : }
4889 : }
4890 0 : return 0;
4891 : }
4892 :
4893 : static int
4894 0 : __vif_fat_flow_ip_prefix_lookup(struct ip_mtrie *mtrie, unsigned int *ip,
4895 : unsigned char *ip6, uint8_t *aggr_mask)
4896 : {
4897 : struct vr_route_req vr_req;
4898 : uint64_t prefix[2];
4899 0 : void *ret = NULL;
4900 :
4901 0 : if (!mtrie) {
4902 0 : return 0;
4903 : }
4904 0 : memset(&vr_req, 0, sizeof(vr_req));
4905 :
4906 0 : if (ip) {
4907 0 : vr_req.rtr_req.rtr_family = AF_INET;
4908 0 : vr_req.rtr_req.rtr_prefix_size = 4;
4909 0 : vr_req.rtr_req.rtr_prefix_len = 32;
4910 0 : prefix[0] = (uint64_t) *ip;
4911 0 : prefix[1] = 0;
4912 : } else {
4913 0 : vr_req.rtr_req.rtr_family = AF_INET6;
4914 0 : vr_req.rtr_req.rtr_prefix_size = 16;
4915 0 : vr_req.rtr_req.rtr_prefix_len = 128;
4916 0 : prefix[0] = *((uint64_t *)ip6);
4917 0 : prefix[1] = *((uint64_t *)((uint8_t *)ip6+8));
4918 : }
4919 :
4920 0 : vr_req.rtr_req.rtr_prefix = (int8_t *)prefix;
4921 0 : ret = vdata_mtrie_lookup(mtrie, &vr_req);
4922 0 : if (!ret || (vr_req.rtr_req.rtr_prefix_len == 0)) {
4923 0 : return 0;
4924 : }
4925 0 : *aggr_mask = (uint8_t) (size_t) ret;
4926 0 : return 1;
4927 : }
4928 :
4929 : static int
4930 0 : vif_fat_flow_prefix_proto_port_match(uint8_t rule_type, int incoming_vif,
4931 : vr_fat_flow_prefix_rule_data_t *rdata,
4932 : unsigned int *dip, unsigned char *dip6,
4933 : uint8_t proto, uint16_t sport, uint16_t dport,
4934 : uint8_t *aggr_mask, uint8_t *aggr_mask1,
4935 : uint16_t *fat_flow_mask)
4936 : {
4937 : int proto_index;
4938 0 : vr_fat_flow_prefix_rule_port_data_t *src_port_info = NULL,
4939 0 : *dst_port_info = NULL,
4940 0 : *zero_port_info = NULL;
4941 0 : vr_itable_t ptable = NULL;
4942 :
4943 0 : proto_index = vif_fat_flow_get_proto_index(proto);
4944 0 : ptable = rdata->proto_info->proto[proto_index];
4945 :
4946 : /* Match protocol and src, dst and 0 port numbers */
4947 0 : if (ptable) {
4948 : /* Set the respective port infos first for the ruletype passed */
4949 0 : src_port_info = (vr_fat_flow_prefix_rule_port_data_t *) vr_itable_get(ptable, sport);
4950 0 : if (src_port_info && (!(src_port_info->rule_type & rule_type))) {
4951 0 : src_port_info = NULL;
4952 : }
4953 :
4954 0 : dst_port_info = (vr_fat_flow_prefix_rule_port_data_t *) vr_itable_get(ptable, dport);
4955 0 : if (dst_port_info && (!(dst_port_info->rule_type & rule_type))) {
4956 0 : dst_port_info = NULL;
4957 : }
4958 :
4959 0 : zero_port_info = (vr_fat_flow_prefix_rule_port_data_t *) vr_itable_get(ptable, 0);
4960 0 : if (zero_port_info && (!(zero_port_info->rule_type & rule_type))) {
4961 0 : zero_port_info = NULL;
4962 : }
4963 :
4964 : /* Now evaluate based on port number precedence */
4965 0 : if (sport < dport) {
4966 0 : if (src_port_info) {
4967 0 : if (rule_type == PREFIX_RULE_TYPE_SINGLE_PREFIX) {
4968 0 : *aggr_mask = src_port_info->aggr_plen;
4969 0 : *fat_flow_mask = VR_FAT_FLOW_DST_PORT_MASK;
4970 0 : if (src_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_SRC) {
4971 0 : *fat_flow_mask |= VR_FAT_FLOW_SRC_IP_MASK;
4972 : }
4973 0 : if (src_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_DST) {
4974 0 : *fat_flow_mask |= VR_FAT_FLOW_DST_IP_MASK;
4975 : }
4976 0 : return 1;
4977 : } else { /* src+dst rule */
4978 0 : if (__vif_fat_flow_ip_prefix_lookup(src_port_info->second_prefix, dip,
4979 : dip6, aggr_mask1)) {
4980 0 : *aggr_mask = src_port_info->aggr_plen;
4981 0 : *fat_flow_mask = VR_FAT_FLOW_DST_PORT_MASK;
4982 0 : return 1;
4983 : }
4984 : }
4985 : }
4986 0 : if (dst_port_info) {
4987 0 : if (rule_type == PREFIX_RULE_TYPE_SINGLE_PREFIX) {
4988 0 : *aggr_mask = dst_port_info->aggr_plen;
4989 0 : *fat_flow_mask = VR_FAT_FLOW_SRC_PORT_MASK;
4990 0 : if (dst_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_SRC) {
4991 0 : *fat_flow_mask |= VR_FAT_FLOW_SRC_IP_MASK;
4992 : }
4993 0 : if (dst_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_DST) {
4994 0 : *fat_flow_mask |= VR_FAT_FLOW_DST_IP_MASK;
4995 : }
4996 0 : return 1;
4997 : } else {
4998 0 : if (__vif_fat_flow_ip_prefix_lookup(dst_port_info->second_prefix, dip,
4999 : dip6, aggr_mask1)) {
5000 0 : *aggr_mask = dst_port_info->aggr_plen;
5001 0 : *fat_flow_mask = VR_FAT_FLOW_SRC_PORT_MASK;
5002 0 : return 1;
5003 : }
5004 : }
5005 : }
5006 : } else {
5007 0 : if (dst_port_info) {
5008 0 : if (rule_type == PREFIX_RULE_TYPE_SINGLE_PREFIX) {
5009 0 : *aggr_mask = dst_port_info->aggr_plen;
5010 0 : *fat_flow_mask = VR_FAT_FLOW_SRC_PORT_MASK;
5011 0 : if (dst_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_SRC) {
5012 0 : *fat_flow_mask |= VR_FAT_FLOW_SRC_IP_MASK;
5013 : }
5014 0 : if (dst_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_DST) {
5015 0 : *fat_flow_mask |= VR_FAT_FLOW_DST_IP_MASK;
5016 : }
5017 0 : return 1;
5018 : } else {
5019 0 : if (__vif_fat_flow_ip_prefix_lookup(dst_port_info->second_prefix,
5020 : dip, dip6, aggr_mask1)) {
5021 0 : *aggr_mask = dst_port_info->aggr_plen;
5022 0 : *fat_flow_mask = VR_FAT_FLOW_SRC_PORT_MASK;
5023 0 : return 1;
5024 : }
5025 : }
5026 : }
5027 0 : if (src_port_info) {
5028 0 : if (rule_type == PREFIX_RULE_TYPE_SINGLE_PREFIX) {
5029 0 : *aggr_mask = src_port_info->aggr_plen;
5030 0 : *fat_flow_mask = VR_FAT_FLOW_DST_PORT_MASK;
5031 0 : if (src_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_SRC) {
5032 0 : *fat_flow_mask |= VR_FAT_FLOW_SRC_IP_MASK;
5033 : }
5034 0 : if (src_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_DST) {
5035 0 : *fat_flow_mask |= VR_FAT_FLOW_DST_IP_MASK;
5036 : }
5037 0 : return 1;
5038 : } else {
5039 0 : if (__vif_fat_flow_ip_prefix_lookup(src_port_info->second_prefix,
5040 : dip, dip6, aggr_mask1)) {
5041 0 : *aggr_mask = src_port_info->aggr_plen;
5042 0 : *fat_flow_mask = VR_FAT_FLOW_DST_PORT_MASK;
5043 0 : return 1;
5044 : }
5045 : }
5046 : }
5047 : }
5048 0 : if (zero_port_info) {
5049 0 : if (rule_type == PREFIX_RULE_TYPE_SINGLE_PREFIX) {
5050 0 : *aggr_mask = zero_port_info->aggr_plen;
5051 0 : *fat_flow_mask =
5052 : (VR_FAT_FLOW_DST_PORT_MASK | VR_FAT_FLOW_SRC_PORT_MASK);
5053 0 : if (zero_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_SRC) {
5054 0 : *fat_flow_mask |= VR_FAT_FLOW_SRC_IP_MASK;
5055 : }
5056 0 : if (zero_port_info->rule_type & PREFIX_RULE_HAS_IGNORE_DST) {
5057 0 : *fat_flow_mask |= VR_FAT_FLOW_DST_IP_MASK;
5058 : }
5059 0 : return 1;
5060 : } else {
5061 0 : if (__vif_fat_flow_ip_prefix_lookup(zero_port_info->second_prefix,
5062 : dip, dip6, aggr_mask1)) {
5063 0 : *aggr_mask = zero_port_info->aggr_plen;
5064 0 : *fat_flow_mask =
5065 : (VR_FAT_FLOW_DST_PORT_MASK | VR_FAT_FLOW_SRC_PORT_MASK);
5066 0 : return 1;
5067 : }
5068 : }
5069 : }
5070 : }
5071 0 : return 0;
5072 : }
5073 :
5074 : static uint16_t
5075 0 : vif_fat_flow_prefix_rule_match(int incoming_vif, struct vr_interface *vif, uint8_t proto,
5076 : uint16_t sport, uint16_t dport, unsigned int *saddr, unsigned int *daddr,
5077 : unsigned char *ip6_src, unsigned char *ip6_dst)
5078 : {
5079 0 : unsigned int *sip_flow = (incoming_vif? saddr: daddr);
5080 0 : unsigned int *dip_flow = (incoming_vif? daddr: saddr);
5081 0 : uint16_t *sport_flow = &sport;
5082 0 : uint16_t *dport_flow = &dport;
5083 0 : unsigned char *sip6_flow = (incoming_vif? ip6_src: ip6_dst);
5084 0 : unsigned char *dip6_flow = (incoming_vif? ip6_dst: ip6_src);
5085 0 : struct vr_route_req vr_req = { { 0, 0} };
5086 : uint64_t prefix[2];
5087 0 : vr_fat_flow_prefix_rule_data_t *rdata_src = NULL,
5088 0 : *rdata_dst = NULL;
5089 : struct ip_mtrie *mtrie_src, *mtrie_dst;
5090 0 : uint16_t fat_flow_mask = 0;
5091 : uint8_t aggr_mask, aggr_mask1;
5092 0 : uint64_t *ip6_h = NULL, *ip6_l = NULL, ip6_mask_h, ip6_mask_l;
5093 :
5094 : /* Lookup with srcip first */
5095 0 : if (saddr) {
5096 0 : vr_req.rtr_req.rtr_family = AF_INET;
5097 0 : vr_req.rtr_req.rtr_prefix_size = 4;
5098 0 : vr_req.rtr_req.rtr_prefix_len = 32;
5099 0 : mtrie_src = vif->vif_fat_flow_v4_src_prefix_rules;
5100 0 : mtrie_dst = vif->vif_fat_flow_v4_dst_prefix_rules;
5101 0 : prefix[0] = (uint64_t) *sip_flow;
5102 0 : prefix[1] = 0;
5103 : } else {
5104 0 : vr_req.rtr_req.rtr_family = AF_INET6;
5105 0 : vr_req.rtr_req.rtr_prefix_size = 16;
5106 0 : vr_req.rtr_req.rtr_prefix_len = 128;
5107 0 : mtrie_src = vif->vif_fat_flow_v6_src_prefix_rules;
5108 0 : mtrie_dst = vif->vif_fat_flow_v6_dst_prefix_rules;
5109 0 : prefix[0] = *((uint64_t *)sip6_flow);
5110 0 : prefix[1] = *((uint64_t *)((uint8_t *)sip6_flow+8));
5111 0 : ip6_h = (uint64_t *) sip6_flow;
5112 0 : ip6_l = (uint64_t *)((uint8_t *)sip6_flow+8);
5113 : }
5114 :
5115 0 : vr_req.rtr_req.rtr_prefix = (int8_t *)prefix;
5116 0 : rdata_src = vdata_mtrie_lookup(mtrie_src, &vr_req);
5117 0 : if (rdata_src && (vr_req.rtr_req.rtr_prefix_len != 0)) {
5118 :
5119 0 : if (vif_fat_flow_prefix_proto_port_match(PREFIX_RULE_TYPE_SINGLE_PREFIX,
5120 : incoming_vif, rdata_src, NULL,
5121 0 : NULL, proto, *sport_flow,
5122 0 : *dport_flow, &aggr_mask, NULL,
5123 : &fat_flow_mask)) {
5124 0 : if (saddr) {
5125 0 : *sip_flow = (*sip_flow) & FAT_FLOW_IPV4_PLEN_TO_MASK(aggr_mask);
5126 : } else {
5127 0 : fat_flow_ipv6_plen_to_mask(aggr_mask, &ip6_mask_h, &ip6_mask_l);
5128 0 : *ip6_h = (*ip6_h) & ip6_mask_h;
5129 0 : *ip6_l = (*ip6_l) & ip6_mask_l;
5130 : }
5131 0 : return fat_flow_mask;
5132 : }
5133 : } else {
5134 : /* reset rdata_src */
5135 0 : rdata_src = NULL;
5136 : }
5137 :
5138 : /* Lookup with dstip now */
5139 0 : if (daddr) {
5140 0 : prefix[0] = (uint64_t) *dip_flow;
5141 0 : prefix[1] = 0;
5142 0 : vr_req.rtr_req.rtr_prefix_len = 32;
5143 : } else {
5144 0 : prefix[0] = *((uint64_t *)dip6_flow);
5145 0 : prefix[1] = *((uint64_t *)((uint8_t *)dip6_flow+8));
5146 0 : vr_req.rtr_req.rtr_prefix_len = 128;
5147 0 : ip6_h = (uint64_t *)dip6_flow;
5148 0 : ip6_l = (uint64_t *)((uint8_t *)dip6_flow+8);
5149 : }
5150 0 : vr_req.rtr_req.rtr_prefix = (int8_t *)prefix;
5151 0 : rdata_dst = vdata_mtrie_lookup(mtrie_dst, &vr_req);
5152 :
5153 0 : if (rdata_dst && (vr_req.rtr_req.rtr_prefix_len != 0)) {
5154 0 : if (vif_fat_flow_prefix_proto_port_match(PREFIX_RULE_TYPE_SINGLE_PREFIX,
5155 : incoming_vif, rdata_dst, NULL,
5156 0 : NULL, proto, *sport_flow,
5157 0 : *dport_flow, &aggr_mask, NULL,
5158 : &fat_flow_mask)) {
5159 0 : if (daddr) {
5160 0 : *dip_flow = (*dip_flow) & FAT_FLOW_IPV4_PLEN_TO_MASK(aggr_mask);
5161 : } else {
5162 0 : fat_flow_ipv6_plen_to_mask(aggr_mask, &ip6_mask_h, &ip6_mask_l);
5163 0 : *ip6_h = (*ip6_h) & ip6_mask_h;
5164 0 : *ip6_l = (*ip6_l) & ip6_mask_l;
5165 : }
5166 0 : return fat_flow_mask;
5167 : }
5168 : }
5169 :
5170 : /* Check for src+dst rule now */
5171 0 : if (rdata_src) {
5172 0 : if (vif_fat_flow_prefix_proto_port_match(PREFIX_RULE_TYPE_DUAL_PREFIX,
5173 : incoming_vif, rdata_src,
5174 : dip_flow, dip6_flow, proto,
5175 0 : *sport_flow, *dport_flow,
5176 : &aggr_mask, &aggr_mask1,
5177 : &fat_flow_mask)) {
5178 0 : if (saddr) {
5179 0 : *sip_flow = (*sip_flow) & FAT_FLOW_IPV4_PLEN_TO_MASK(aggr_mask);
5180 : } else {
5181 0 : fat_flow_ipv6_plen_to_mask(aggr_mask, &ip6_mask_h, &ip6_mask_l);
5182 0 : ip6_h = (uint64_t *) sip6_flow;
5183 0 : ip6_l = (uint64_t *)((uint8_t *)sip6_flow+8);
5184 0 : *ip6_h = (*ip6_h) & ip6_mask_h;
5185 0 : *ip6_l = (*ip6_l) & ip6_mask_l;
5186 : }
5187 0 : if (daddr) {
5188 0 : *dip_flow = (*dip_flow) & FAT_FLOW_IPV4_PLEN_TO_MASK(aggr_mask1);
5189 : } else {
5190 0 : fat_flow_ipv6_plen_to_mask(aggr_mask1, &ip6_mask_h, &ip6_mask_l);
5191 0 : ip6_h = (uint64_t *)dip6_flow;
5192 0 : ip6_l = (uint64_t *)((uint8_t *)dip6_flow+8);
5193 0 : *ip6_h = (*ip6_h) & ip6_mask_h;
5194 0 : *ip6_l = (*ip6_l) & ip6_mask_l;
5195 : }
5196 0 : return fat_flow_mask;
5197 : }
5198 : }
5199 0 : return fat_flow_mask;
5200 : }
5201 :
5202 :
5203 : uint16_t
5204 57 : vif_fat_flow_lookup(int incoming_vif, struct vr_interface *vif, uint8_t proto,
5205 : uint16_t sport, uint16_t dport, unsigned int *saddr, unsigned int *daddr,
5206 : unsigned char *ip6_src, unsigned char *ip6_dst)
5207 : {
5208 57 : uint8_t fat_flow_mask = 0, sport_mask = 0, dport_mask = 0;
5209 : uint16_t h_sport, h_dport;
5210 : unsigned int proto_index;
5211 :
5212 : /* Check if the IPs belong to exclude list, if so return NO_MASK */
5213 57 : if (vif_fat_flow_exclude_list_lookup(vif, saddr, daddr, ip6_src, ip6_dst)) {
5214 0 : return fat_flow_mask;
5215 : }
5216 :
5217 57 : proto_index = vif_fat_flow_get_proto_index(proto);
5218 57 : if (!vif->fat_flow_num_rules[proto_index])
5219 57 : return fat_flow_mask;
5220 :
5221 0 : if (proto_index == VIF_FAT_FLOW_NOPROTO_INDEX) {
5222 : /*
5223 : * Both ICMPv6 and ICMP rules are stored with proto 1,
5224 : * hence override in case of ICMPv6
5225 : */
5226 0 : if (proto == VR_IP_PROTO_ICMP6) {
5227 0 : proto = VR_IP_PROTO_ICMP;
5228 : }
5229 0 : h_sport = h_dport = proto;
5230 : } else {
5231 0 : h_sport = ntohs(sport);
5232 0 : h_dport = ntohs(dport);
5233 : }
5234 :
5235 : /*
5236 : * If there is a specific port configuration exists - it takes
5237 : * precedence
5238 : * If both ports have configuration - smallest port takes precedence
5239 : * If no specific port configuration exists, but port "0"
5240 : * configuration exists, use that as fat flow config
5241 : */
5242 0 : sport_mask = vif_fat_flow_port_get(vif, proto_index, h_sport);
5243 0 : dport_mask = vif_fat_flow_port_get(vif, proto_index, h_dport);
5244 :
5245 0 : if (sport_mask || dport_mask) {
5246 0 : if (sport_mask && dport_mask) {
5247 0 : if (proto_index != VIF_FAT_FLOW_NOPROTO_INDEX) {
5248 0 : if (h_dport <= h_sport)
5249 0 : sport_mask = 0;
5250 : else
5251 0 : dport_mask = 0;
5252 : }
5253 : }
5254 : } else {
5255 0 : sport_mask = vif_fat_flow_port_get(vif, proto_index, 0);
5256 0 : if (sport_mask) {
5257 0 : fat_flow_mask |= (VR_FAT_FLOW_DST_PORT_MASK |
5258 : VR_FAT_FLOW_SRC_PORT_MASK);
5259 : }
5260 : }
5261 :
5262 0 : if (sport_mask == VIF_FAT_FLOW_PORT_SET)
5263 0 : fat_flow_mask |= VR_FAT_FLOW_DST_PORT_MASK;
5264 :
5265 0 : if (dport_mask == VIF_FAT_FLOW_PORT_SET)
5266 0 : fat_flow_mask |= VR_FAT_FLOW_SRC_PORT_MASK;
5267 :
5268 0 : if (sport_mask == VIF_FAT_FLOW_PORT_SIP_IGNORE)
5269 0 : fat_flow_mask |= (VR_FAT_FLOW_SRC_IP_MASK | VR_FAT_FLOW_DST_PORT_MASK);
5270 :
5271 0 : if (sport_mask == VIF_FAT_FLOW_PORT_DIP_IGNORE)
5272 0 : fat_flow_mask |= (VR_FAT_FLOW_DST_IP_MASK | VR_FAT_FLOW_DST_PORT_MASK);
5273 :
5274 0 : if (dport_mask == VIF_FAT_FLOW_PORT_SIP_IGNORE)
5275 0 : fat_flow_mask |= (VR_FAT_FLOW_SRC_IP_MASK | VR_FAT_FLOW_SRC_PORT_MASK);
5276 :
5277 0 : if (dport_mask == VIF_FAT_FLOW_PORT_DIP_IGNORE)
5278 0 : fat_flow_mask |= (VR_FAT_FLOW_DST_IP_MASK | VR_FAT_FLOW_SRC_PORT_MASK);
5279 :
5280 0 : if (fat_flow_mask) {
5281 0 : return fat_flow_mask;
5282 : }
5283 :
5284 : /* Check prefix aggregation rules to see if there is a match there */
5285 0 : return vif_fat_flow_prefix_rule_match(incoming_vif, vif, proto,
5286 : h_sport, h_dport, saddr, daddr,
5287 : ip6_src, ip6_dst);
5288 : }
5289 :
5290 :
5291 : int
5292 0 : vr_gro_vif_add(struct vrouter *router, unsigned int os_idx, char *name,
5293 : unsigned short idx)
5294 : {
5295 0 : int ret = 0;
5296 0 : vr_interface_req *req = vr_interface_req_get();
5297 :
5298 0 : if (!req)
5299 0 : return -ENOMEM;
5300 :
5301 0 : req->h_op = SANDESH_OP_ADD;
5302 0 : req->vifr_type = VIF_TYPE_STATS;
5303 0 : req->vifr_flags = 0;
5304 0 : req->vifr_vrf = 65535;
5305 0 : req->vifr_mcast_vrf = 65535;
5306 0 : req->vifr_idx = idx;
5307 0 : req->vifr_rid = 0;
5308 0 : req->vifr_transport = VIF_TRANSPORT_ETH;
5309 0 : req->vifr_os_idx = os_idx;
5310 0 : req->vifr_mtu = 9136;
5311 :
5312 0 : if (req->vifr_name) {
5313 0 : strncpy(req->vifr_name, name, VR_INTERFACE_NAME_LEN - 1);
5314 : }
5315 :
5316 0 : ret = vr_interface_add(req, false);
5317 0 : vr_interface_req_destroy(req);
5318 :
5319 0 : return ret;
5320 : }
5321 :
5322 : /*
5323 : * this makes sure that packets no longer enter the module when
5324 : * we remove the module
5325 : */
5326 : void
5327 53 : vr_interface_shut(struct vrouter *router)
5328 : {
5329 : unsigned int i;
5330 : struct vr_interface *vif;
5331 :
5332 53 : if (!router->vr_interfaces)
5333 0 : return;
5334 :
5335 230868 : for (i = 0; i < router->vr_max_interfaces; i++) {
5336 230815 : if ((vif = router->vr_interfaces[i])) {
5337 3 : vif->vif_tx = vif_discard_tx;
5338 3 : vif->vif_rx = vif_discard_rx;
5339 3 : vif_drv_delete(vif);
5340 3 : vif->vif_flags = 0;
5341 : }
5342 : }
5343 :
5344 53 : vr_delay_op();
5345 : /* after this, we have a free hand */
5346 :
5347 53 : return;
5348 : }
5349 :
5350 : void
5351 53 : vr_interface_exit(struct vrouter *router, bool soft_reset)
5352 : {
5353 : unsigned int i;
5354 : struct vr_interface *vif;
5355 :
5356 53 : if (!router)
5357 0 : return;
5358 :
5359 53 : if (router->vr_interfaces) {
5360 230868 : for (i = 0; i < router->vr_max_interfaces; i++)
5361 230815 : if ((vif = router->vr_interfaces[i]))
5362 3 : vrouter_del_interface(vif);
5363 : }
5364 :
5365 :
5366 53 : if (!soft_reset) {
5367 53 : vr_host_interface_exit();
5368 53 : hif_ops = NULL;
5369 : }
5370 :
5371 53 : if (!soft_reset && router->vr_interfaces) {
5372 53 : vr_free(router->vr_interfaces, VR_INTERFACE_TABLE_OBJECT);
5373 53 : router->vr_interfaces = NULL;
5374 53 : router->vr_max_interfaces = 0;
5375 : }
5376 :
5377 53 : return;
5378 : }
5379 :
5380 : int
5381 53 : vr_interface_init(struct vrouter *router)
5382 : {
5383 53 : int ret = 0;
5384 53 : unsigned int table_memory = 0;
5385 :
5386 53 : if (!router->vr_interfaces) {
5387 53 : router->vr_max_interfaces = vr_interfaces;
5388 53 : table_memory = router->vr_max_interfaces *
5389 : sizeof(struct vr_interface *);
5390 53 : router->vr_interfaces = vr_zalloc(table_memory,
5391 : VR_INTERFACE_TABLE_OBJECT);
5392 53 : if (!router->vr_interfaces && (ret = -ENOMEM))
5393 0 : return vr_module_error(ret, __FUNCTION__,
5394 : __LINE__, table_memory);
5395 : }
5396 :
5397 53 : if (!hif_ops) {
5398 53 : hif_ops = vr_host_interface_init();
5399 53 : if (!hif_ops && (ret = -ENOMEM)) {
5400 0 : vr_module_error(ret, __FUNCTION__, __LINE__, 0);
5401 0 : goto cleanup;
5402 : }
5403 : }
5404 :
5405 53 : vr_host_vif_init(router);
5406 :
5407 53 : return 0;
5408 :
5409 0 : cleanup:
5410 0 : if (router->vr_interfaces) {
5411 0 : vr_free(router->vr_interfaces, VR_INTERFACE_TABLE_OBJECT);
5412 0 : router->vr_interfaces = NULL;
5413 0 : router->vr_max_interfaces = 0;
5414 : }
5415 :
5416 0 : return ret;
5417 : }
|