LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dp-core - vr_interface.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 1068 2837 37.6 %
Date: 2026-08-03 02:19:58 Functions: 69 124 55.6 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.14