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