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

Generated by: LCOV version 1.14