---
 drivers/net/ethernet/cavium/thunder/pf_filter.c | 1678 +++++++++++++++++++++++
 1 file changed, 1678 insertions(+)
 create mode 100644 drivers/net/ethernet/cavium/thunder/pf_filter.c

diff --git a/drivers/net/ethernet/cavium/thunder/pf_filter.c 
b/drivers/net/ethernet/cavium/thunder/pf_filter.c
new file mode 100644
index 0000000..5a04da6
--- /dev/null
+++ b/drivers/net/ethernet/cavium/thunder/pf_filter.c
@@ -0,0 +1,1678 @@
+/*
+ * Copyright (C) 2015 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+#include <linux/mman.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include "pf_globals.h"
+#include "pf_locals.h"
+#include "nic.h"
+
+u32 intr_to_ingressgrp[MAX_NUMNODES][TNS_MAC_FILTER_MAX_SYS_PORTS];
+struct vf_register_s vf_reg_data[MAX_NUMNODES][TNS_MAX_VF];
+struct ing_grp_gblvif ingressgrp_gblvif[MAX_NUMNODES][TNS_MAX_INGRESS_GROUP];
+
+u32 macfilter_freeindex[MAX_NUMNODES];
+u32 vlanfilter_freeindex[MAX_NUMNODES];
+
+int tns_filter_valid_entry(int node, int req_type, int vf, int vlan)
+{
+       if (req_type == NIC_MBOX_MSG_UC_MC) {
+               if (vf_reg_data[node][vf].vf_in_mcast_promis ||
+                   (macfilter_freeindex[node] >= TNS_MAC_FILTER_MAX_INDEX))
+                       return TNS_ERR_MAX_LIMIT;
+               if (vf_reg_data[node][vf].filter_count >= TNS_MAX_MAC_PER_VF) {
+                       tns_enable_mcast_promis(node, vf);
+                       vf_reg_data[node][vf].vf_in_mcast_promis = 1;
+                       return TNS_ERR_MAX_LIMIT;
+               }
+       } else if (req_type == NIC_MBOX_MSG_VLAN ||
+                  req_type == NIC_MBOX_MSG_ADMIN_VLAN) {
+               if (vf_reg_data[node][vf].vlan_count >= TNS_MAX_VLAN_PER_VF)
+                       return TNS_ERR_MAX_LIMIT;
+
+               if (vlanfilter_freeindex[node] >= TNS_VLAN_FILTER_MAX_INDEX) {
+                       int ret;
+                       struct vlan_filter_entry tbl_entry;
+                       int vlan_tbl_idx = -1;
+
+                       tbl_entry.key.is_valid = 1;
+                       tbl_entry.key.key_type.key_value  = 0x0ull;
+                       tbl_entry.mask.key_type.key_value = ~0x0ull;
+                       tbl_entry.key.key_type.s.ingress_grp =
+                               intr_to_ingressgrp[node][vf];
+                       tbl_entry.mask.key_type.s.ingress_grp = 0x0;
+                       tbl_entry.key.key_type.s.vlan = vlan;
+                       tbl_entry.mask.key_type.s.vlan = 0x0;
+
+                       ret = filter_tbl_lookup(node, VLAN_FILTER_TABLE,
+                                               &tbl_entry, &vlan_tbl_idx);
+                       if (ret || vlan_tbl_idx == -1)
+                               return TNS_ERR_MAX_LIMIT;
+               }
+       } else {
+               filter_dbg(FERR, "Invalid Request %d VF %d\n", req_type, vf);
+       }
+
+       return TNS_NO_ERR;
+}
+
+int dump_port_cfg_etry(struct itt_entry_s *port_cfg_entry)
+{
+       filter_dbg(FINFO, "PortConfig Entry\n");
+       filter_dbg(FINFO, "pkt_dir:                     0x%x\n",
+                  port_cfg_entry->pkt_dir);
+       filter_dbg(FINFO, "is_admin_vlan_enabled:       0x%x\n",
+                  port_cfg_entry->is_admin_vlan_enabled);
+       filter_dbg(FINFO, "default_evif:                0x%x\n",
+                  port_cfg_entry->default_evif);
+       filter_dbg(FINFO, "admin_vlan:                  0x%x\n",
+                  port_cfg_entry->admin_vlan);
+
+       return TNS_NO_ERR;
+}
+
+int dump_evif_entry(struct evif_entry *evif_dat)
+{
+       filter_dbg(FINFO, "EVIF Entry\n");
+       filter_dbg(FINFO, "prt_bmap_136_73: 0x%llx\n",
+                  evif_dat->prt_bmap_136_73);
+       filter_dbg(FINFO, "prt_bmap_72_9:   0x%llx\n",
+                  evif_dat->prt_bmap_72_9);
+       filter_dbg(FINFO, "prt_bmap_8:      0x%x\n", evif_dat->prt_bmap_8);
+       filter_dbg(FINFO, "mre_ptr:         0x%x\n", evif_dat->mre_ptr);
+       filter_dbg(FINFO, "insert_ptr2:     0x%x\n", evif_dat->insert_ptr2);
+       filter_dbg(FINFO, "insert_ptr1:     0x%x\n", evif_dat->insert_ptr1);
+       filter_dbg(FINFO, "insert_ptr0:     0x%x\n", evif_dat->insert_ptr0);
+       filter_dbg(FINFO, "data31_0:        0x%x\n", evif_dat->data31_0);
+       filter_dbg(FINFO, "rewrite_ptr1:    0x%x\n", evif_dat->rewrite_ptr1);
+       filter_dbg(FINFO, "rewrite_ptr0:    0x%x\n", evif_dat->rewrite_ptr0);
+       filter_dbg(FINFO, "prt_bmap7_0:     0x%x\n", evif_dat->prt_bmap7_0);
+       filter_dbg(FINFO, "q_mirror_en:     0x%x\n", evif_dat->q_mirror_en);
+       filter_dbg(FINFO, "mirror_en:       0x%x\n", evif_dat->mirror_en);
+       filter_dbg(FINFO, "mtu_prf:         0x%x\n", evif_dat->mtu_prf);
+       filter_dbg(FINFO, "truncate:        0x%x\n", evif_dat->truncate);
+       filter_dbg(FINFO, "rsp_type:        0x%x\n", evif_dat->rsp_type);
+
+       return TNS_NO_ERR;
+}
+
+static inline int validate_port(int port_num)
+{
+       if (port_num < 0 && port_num >= TNS_MAC_FILTER_MAX_SYS_PORTS) {
+               filter_dbg(FERR, "%s Invalid Port: %d (Valid range 0-136)\n",
+                          __func__, port_num);
+               return TNS_ERR_WRONG_PORT_NUMBER;
+       }
+       return TNS_NO_ERR;
+}
+
+int enable_port(int port_num, struct evif_entry *tbl_entry)
+{
+       s64 port_base;
+
+       if (validate_port(port_num))
+               return TNS_ERR_WRONG_PORT_NUMBER;
+
+       if (port_num < 8) {
+               tbl_entry->prt_bmap7_0 = tbl_entry->prt_bmap7_0 |
+                                        (0x1 << port_num);
+       } else if (port_num == 8) {
+               tbl_entry->prt_bmap_8 = 1;
+       } else if (port_num <= 72) {
+               port_base = port_num - 9;
+               tbl_entry->prt_bmap_72_9 = tbl_entry->prt_bmap_72_9 |
+                                               (0x1ull << port_base);
+       } else if (port_num <= TNS_MAC_FILTER_MAX_SYS_PORTS) {
+               port_base = port_num - 73;
+               tbl_entry->prt_bmap_136_73 = tbl_entry->prt_bmap_136_73 |
+                                               (0x1ull << port_base);
+       }
+
+       return TNS_NO_ERR;
+}
+
+int disable_port(int port_num, struct evif_entry *tbl_entry)
+{
+       s64 port_base;
+
+       if (validate_port(port_num))
+               return TNS_ERR_WRONG_PORT_NUMBER;
+
+       if (port_num < 8) {
+               tbl_entry->prt_bmap7_0 = tbl_entry->prt_bmap7_0 &
+                                        ~(0x1 << port_num);
+       } else if (port_num == 8) {
+               tbl_entry->prt_bmap_8 = 0;
+       } else if (port_num <= 72) {
+               port_base = port_num - 9;
+               tbl_entry->prt_bmap_72_9 = tbl_entry->prt_bmap_72_9 &
+                                               ~(0x1ull << port_base);
+       } else if (port_num <= TNS_MAC_FILTER_MAX_SYS_PORTS) {
+               port_base = port_num - 73;
+               tbl_entry->prt_bmap_136_73 = tbl_entry->prt_bmap_136_73 &
+                                               ~(0x1ull << port_base);
+       }
+
+       return TNS_NO_ERR;
+}
+
+int disable_all_ports(struct evif_entry *tbl_entry)
+{
+       tbl_entry->prt_bmap_136_73 = 0x0ull;
+       tbl_entry->prt_bmap_72_9 = 0x0ull;
+       tbl_entry->prt_bmap_8 = 0x0;
+       tbl_entry->prt_bmap7_0 = 0x0;
+
+       return TNS_NO_ERR;
+}
+
+int is_vlan_port_enabled(int vf, vlan_port_bitmap_t vlan_vif)
+{
+       int port_base = (vf / 8), port_offset = (vf % 8);
+
+       if (validate_port(vf))
+               return TNS_ERR_WRONG_PORT_NUMBER;
+
+       if (vlan_vif[port_base] & (1 << port_offset))
+               return 1;
+
+       return 0;
+}
+
+int enable_vlan_port(int port_num, vlan_port_bitmap_t vlan_vif)
+{
+       int port_base = (port_num / 8), port_offset = (port_num % 8);
+
+       if (validate_port(port_num))
+               return TNS_ERR_WRONG_PORT_NUMBER;
+
+       vlan_vif[port_base] = vlan_vif[port_base] | (1 << port_offset);
+
+       return TNS_NO_ERR;
+}
+
+int disable_vlan_port(int port_num, vlan_port_bitmap_t vlan_vif)
+{
+       int port_base = (port_num / 8), port_offset = (port_num % 8);
+
+       if (validate_port(port_num))
+               return TNS_ERR_WRONG_PORT_NUMBER;
+
+       vlan_vif[port_base] = vlan_vif[port_base] & ~(1 << port_offset);
+
+       return TNS_NO_ERR;
+}
+
+int disable_vlan_vif_ports(vlan_port_bitmap_t vlan_vif)
+{
+       memset((void *)(&vlan_vif[0]), 0x0, sizeof(vlan_port_bitmap_t));
+
+       return TNS_NO_ERR;
+}
+
+int dump_vlan_vif_portss(vlan_port_bitmap_t vlan_vif)
+{
+       int i;
+
+       filter_dbg(FINFO, "Port Bitmap (0...135) 0x ");
+       for (i = 0; i < (TNS_MAC_FILTER_MAX_SYS_PORTS / 8); i++)
+               filter_dbg(FINFO, "%x ", vlan_vif[i]);
+       filter_dbg(FINFO, "\n");
+
+       return TNS_NO_ERR;
+}
+
+static inline int getingress_grp(int node, int vf)
+{
+       int i;
+
+       for (i = 0; i < TNS_MAX_INGRESS_GROUP; i++) {
+               if (ingressgrp_gblvif[node][i].is_valid &&
+                   (ingressgrp_gblvif[node][i].ingress_grp ==
+                    intr_to_ingressgrp[node][vf]))
+                       return i;
+       }
+       return -1;
+}
+
+inline int vf_bcast_vif(int node, int vf, int *bcast_vif)
+{
+       int ing_grp = getingress_grp(node, vf);
+
+       if (ing_grp == -1)
+               return TNS_ERR_ENTRY_NOT_FOUND;
+
+       *bcast_vif = ingressgrp_gblvif[node][ing_grp].bcast_vif;
+
+       return TNS_NO_ERR;
+}
+
+inline int vf_mcast_vif(int node, int vf, int *mcast_vif)
+{
+       int ing_grp = getingress_grp(node, vf);
+
+       if (ing_grp == -1)
+               return TNS_ERR_ENTRY_NOT_FOUND;
+
+       *mcast_vif = ingressgrp_gblvif[node][ing_grp].mcast_vif;
+
+       return TNS_NO_ERR;
+}
+
+inline int vf_pfvf_id(int node, int vf, int *pfvf)
+{
+       int ing_grp = getingress_grp(node, vf);
+
+       if (ing_grp == -1)
+               return TNS_ERR_ENTRY_NOT_FOUND;
+
+       *pfvf = ingressgrp_gblvif[node][ing_grp].pf_vf;
+
+       return TNS_NO_ERR;
+}
+
+bool is_vf_registered_entry(int node, int vf, int index)
+{
+       int i;
+
+       for (i = 0; i < vf_reg_data[node][vf].filter_count; i++) {
+               if (vf_reg_data[node][vf].filter_index[i] == index)
+                       return true;
+       }
+
+       return false;
+}
+
+bool is_vlan_registered(int node, int vf, int vlan)
+{
+       int i;
+
+       for (i = 0; i < vf_reg_data[node][vf].vlan_count; i++) {
+               if (vf_reg_data[node][vf].vlan[i] == vlan)
+                       return true;
+       }
+
+       return false;
+}
+
+int is_empty_vif(int node, int vf, struct evif_entry *evif_dat)
+{
+       int i;
+
+       for (i = 0; i < TNS_MAX_VF; i++)
+               if (intr_to_ingressgrp[node][vf] ==
+                   intr_to_ingressgrp[node][i] &&
+                   (vf_reg_data[node][i].vf_in_promis ||
+                    vf_reg_data[node][i].vf_in_mcast_promis))
+                       disable_port(i, evif_dat);
+       disable_port(intr_to_ingressgrp[node][vf], evif_dat);
+
+       if (evif_dat->prt_bmap7_0 || evif_dat->prt_bmap_8 ||
+           evif_dat->prt_bmap_72_9 || evif_dat->prt_bmap_136_73)
+               return 0;
+
+       return 1;
+}
+
+int is_empty_vlan(int node, int vf, int vlan, vlan_port_bitmap_t vlan_vif)
+{
+       int i, pf_vf;
+       int ret;
+
+       ret = vf_pfvf_id(node, vf, &pf_vf);
+       if (ret)
+               return ret;
+
+       if (vf_reg_data[node][pf_vf].vf_in_promis &&
+           !is_vlan_registered(node, pf_vf, vlan))
+               disable_vlan_port(pf_vf, vlan_vif);
+
+       disable_vlan_port(intr_to_ingressgrp[node][vf], vlan_vif);
+       for (i = 0; i < sizeof(vlan_port_bitmap_t); i++)
+               if (vlan_vif[i])
+                       break;
+
+       if (i == sizeof(vlan_port_bitmap_t))
+               return 1;
+
+       return 0;
+}
+
+int filter_tbl_lookup(int node, int table_id, void *entry, int *index)
+{
+       switch (table_id) {
+       case MAC_FILTER_TABLE:
+       {
+               struct mac_filter_entry tbl_entry;
+               struct mac_filter_entry *inp = (struct mac_filter_entry *)entry;
+               int i;
+               int ret;
+
+               for (i = 0; i < TNS_MAC_FILTER_MAX_INDEX; i++) {
+                       ret = tbl_read(node, MAC_FILTER_TABLE, i,
+                                      &tbl_entry.key, &tbl_entry.mask,
+                                      &tbl_entry.data);
+
+                       if (ret && (ret != TNS_ERR_MAC_FILTER_INVALID_ENTRY))
+                               return ret;
+                       else if (ret == TNS_ERR_MAC_FILTER_INVALID_ENTRY)
+                               continue;
+
+                       if ((tbl_entry.key.key_type.key_value ==
+                            inp->key.key_type.key_value) &&
+                           (tbl_entry.mask.key_type.key_value ==
+                            inp->mask.key_type.key_value)) {
+                               //Found an Entry
+                               *index = i;
+                               inp->data.data = tbl_entry.data.data;
+                               return TNS_NO_ERR;
+                       }
+                       //Unable to find entry
+                       *index = -1;
+               }
+               break;
+       }
+       case VLAN_FILTER_TABLE:
+       {
+               struct vlan_filter_entry tbl_entry;
+               struct vlan_filter_entry *inp_entry;
+               int i;
+               int ret;
+
+               inp_entry = (struct vlan_filter_entry *)entry;
+               for (i = 1; i < TNS_VLAN_FILTER_MAX_INDEX; i++) {
+                       ret = tbl_read(node, VLAN_FILTER_TABLE, i,
+                                      &tbl_entry.key, &tbl_entry.mask,
+                                       &tbl_entry.data);
+                       if (ret && (ret != TNS_ERR_MAC_FILTER_INVALID_ENTRY))
+                               return ret;
+                       else if (ret == TNS_ERR_MAC_FILTER_INVALID_ENTRY)
+                               continue;
+
+                       if ((tbl_entry.key.key_type.key_value ==
+                            inp_entry->key.key_type.key_value) &&
+                           (tbl_entry.mask.key_type.key_value ==
+                            inp_entry->mask.key_type.key_value)) {
+                               //Found an Entry
+                               *index = i;
+                               inp_entry->data.data = tbl_entry.data.data;
+                               return TNS_NO_ERR;
+                       }
+               }
+               //Unable to find entry
+               *index = -1;
+               break;
+       }
+       default:
+               filter_dbg(FERR, "Wrong Table ID: %d\n", table_id);
+               return TNS_ERR_INVALID_TBL_ID;
+       }
+
+       return TNS_NO_ERR;
+}
+
+int tns_enable_mcast_promis(int node, int vf)
+{
+       int mcast_vif;
+       int j;
+       int ret;
+       struct evif_entry evif_dat;
+       int ing_grp = getingress_grp(node, vf);
+       int pports;
+
+       if (ing_grp == -1)
+               return TNS_ERROR_INVALID_ARG;
+
+       ret = vf_mcast_vif(node, vf, &mcast_vif);
+       if (ret) {
+               filter_dbg(FERR, "Error: Unable to get multicast VIF\n");
+               return ret;
+       }
+
+       ret = tbl_read(node, MAC_EVIF_TABLE, mcast_vif, NULL, NULL, &evif_dat);
+       if (ret)
+               return ret;
+
+       enable_port(vf, &evif_dat);
+       dump_evif_entry(&evif_dat);
+       ret = tbl_write(node, MAC_EVIF_TABLE, mcast_vif, NULL, NULL,
+                       (void *)&evif_dat);
+       if (ret)
+               return ret;
+
+       pports = ingressgrp_gblvif[node][ing_grp].valid_mcast_promis_ports;
+       //Enable VF in multicast MAC promiscuous group
+       for (j = 0; j < pports; j++) {
+               if (MCAST_PROMIS(node, ing_grp, j) == vf) {
+                       filter_dbg(FDEBUG, "VF found in MCAST promis group\n");
+                       return TNS_NO_ERR;
+               }
+       }
+       MCAST_PROMIS(node, ing_grp, pports) = vf;
+       ingressgrp_gblvif[node][ing_grp].valid_mcast_promis_ports += 1;
+       filter_dbg(FINFO, "VF %d permanently entered into MCAST promisc mode\n",
+                  vf);
+
+       return TNS_NO_ERR;
+}
+
+int remove_vf_from_regi_mcast_vif(int node, int vf)
+{
+       int ret;
+       int mcast_vif;
+       struct evif_entry evif_dat;
+
+       ret = vf_mcast_vif(node, vf, &mcast_vif);
+       if (ret) {
+               filter_dbg(FERR, "Error: Unable to get multicast VIF\n");
+               return ret;
+       }
+
+       ret = tbl_read(node, MAC_EVIF_TABLE, mcast_vif, NULL, NULL, &evif_dat);
+       if (ret)
+               return ret;
+       disable_port(vf, &evif_dat);
+       dump_evif_entry(&evif_dat);
+       ret = tbl_write(node, MAC_EVIF_TABLE, mcast_vif, NULL, NULL,
+                       (void *)&evif_dat);
+       if (ret)
+               return ret;
+
+       return TNS_NO_ERR;
+}
+
+int remove_vf_from_mcast_promis_grp(int node, int vf)
+{
+       int j, k;
+       int ing_grp = getingress_grp(node, vf);
+       int pports;
+
+       if (ing_grp == -1)
+               return TNS_ERROR_INVALID_ARG;
+
+       pports = ingressgrp_gblvif[node][ing_grp].valid_mcast_promis_ports;
+       for (j = 0; j < pports; j++) {
+               if (MCAST_PROMIS(node, ing_grp, j) != vf)
+                       continue;
+
+               filter_dbg(FDEBUG, "VF found in MCAST promis group %d\n",
+                          intr_to_ingressgrp[node][vf]);
+               for (k = j; k < (pports - 1); k++)
+                       MCAST_PROMIS(node, ing_grp, k) =
+                        MCAST_PROMIS(node, ing_grp, (k + 1));
+               VALID_MCAST_PROMIS(node, ing_grp) -= 1;
+               remove_vf_from_regi_mcast_vif(node, vf);
+               return TNS_NO_ERR;
+       }
+       filter_dbg(FDEBUG, "VF %d not found in multicast promiscuous group\n",
+                  vf);
+
+       return TNS_ERR_ENTRY_NOT_FOUND;
+}
+
+int registered_vf_filter_index(int node, int vf, int mac_idx, int action)
+{
+       int f_count = vf_reg_data[node][vf].filter_count, j;
+
+       if (!action) {
+               for (j = 0; j < f_count; j++) {
+                       if (vf_reg_data[node][vf].filter_index[j] == mac_idx) {
+                               int i, k = j + 1;
+
+                               for (i = j; i < f_count - 1; i++, k++)
+                                       vf_reg_data[node][vf].filter_index[i] =
+                                        vf_reg_data[node][vf].filter_index[k];
+                               break;
+                       }
+               }
+               if (j == vf_reg_data[node][vf].filter_count)
+                       filter_dbg(FDEBUG, "VF not in registered filtr list\n");
+               else
+                       vf_reg_data[node][vf].filter_count -= 1;
+       } else {
+               vf_reg_data[node][vf].filter_index[f_count] = mac_idx;
+               vf_reg_data[node][vf].filter_count += 1;
+               filter_dbg(FINFO, "%s Added at Filter count %d Index %d\n",
+                          __func__, vf_reg_data[node][vf].filter_count,
+                          mac_idx);
+       }
+
+       /* We are restricting each VF to register atmost 11 filter entries
+        * (including unicast & multicast)
+        */
+       if (vf_reg_data[node][vf].filter_count <= TNS_MAX_MAC_PER_VF) {
+               vf_reg_data[node][vf].vf_in_mcast_promis = 0;
+               if (!vf_reg_data[node][vf].vf_in_promis)
+                       remove_vf_from_mcast_promis_grp(node, vf);
+               filter_dbg(FINFO, "VF %d removed from MCAST promis mode\n", vf);
+       }
+
+       return TNS_NO_ERR;
+}
+
+int add_mac_filter_mcast_entry(int node, int table_id, int vf, int mac_idx,
+                              void *mac_DA)
+{
+       int ret;
+       struct mac_filter_entry tbl_entry;
+       struct mac_filter_keymask_s key, mask;
+       union mac_filter_data_s data;
+       int vif = -1, k, j;
+       struct evif_entry evif_dat;
+       int ing_grp = getingress_grp(node, vf);
+
+       if (ing_grp == -1)
+               return TNS_ERROR_INVALID_ARG;
+
+       if (vf_reg_data[node][vf].filter_count >= TNS_MAX_MAC_PER_VF) {
+               if (!vf_reg_data[node][vf].vf_in_mcast_promis) {
+                       tns_enable_mcast_promis(node, vf);
+                       vf_reg_data[node][vf].vf_in_mcast_promis = 1;
+               }
+               return TNS_ERR_MAX_LIMIT;
+       }
+
+       tbl_entry.key.is_valid = 1;
+       tbl_entry.key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       tbl_entry.mask.key_type.s.ingress_grp = 0x0;
+       for (j = 5, k = 0; j >= 0; j--, k++) {
+               tbl_entry.key.key_type.s.mac_DA[k] = ((u8 *)mac_DA)[j];
+               tbl_entry.mask.key_type.s.mac_DA[k] = 0x0;
+       }
+       ret = filter_tbl_lookup(node, MAC_FILTER_TABLE, &tbl_entry, &mac_idx);
+       if (ret)
+               return ret;
+       if (mac_idx != -1 &&
+           !(mac_idx >= (TNS_MAC_FILTER_MAX_INDEX - TNS_MAX_INGRESS_GROUP) &&
+             mac_idx < TNS_MAC_FILTER_MAX_INDEX)) {
+               int evif = tbl_entry.data.s.evif;
+
+               filter_dbg(FINFO, "Multicast MAC found at %d evif: %d\n",
+                          mac_idx, evif);
+               ret = tbl_read(node, MAC_EVIF_TABLE, evif, NULL, NULL,
+                              &evif_dat);
+               if (ret)
+                       return ret;
+               if (is_vf_registered_entry(node, vf, mac_idx)) {
+                       //No Need to register again
+                       return TNS_NO_ERR;
+               }
+               enable_port(vf, &evif_dat);
+               ret = tbl_write(node, MAC_EVIF_TABLE, evif, NULL, NULL,
+                               (void *)&evif_dat);
+               if (ret)
+                       return ret;
+               registered_vf_filter_index(node, vf, mac_idx, 1);
+               dump_evif_entry(&evif_dat);
+               return TNS_NO_ERR;
+       }
+
+       //New multicast MAC registration
+       if (alloc_table_index(node, MAC_FILTER_TABLE, &mac_idx)) {
+               filter_dbg(FERR, "%s Filter Table Full\n", __func__);
+               return TNS_ERR_MAX_LIMIT;
+       }
+       key.is_valid = 1;
+       mask.is_valid = 1;
+       key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       mask.key_type.s.ingress_grp = 0;
+       for (j = 5, k = 0; j >= 0; j--, k++) {
+               key.key_type.s.mac_DA[k] = ((u8 *)mac_DA)[j];
+               mask.key_type.s.mac_DA[k] = 0x0;
+       }
+       if (alloc_table_index(node, MAC_EVIF_TABLE, &vif)) {
+               filter_dbg(FERR, "%s EVIF Table Full\n", __func__);
+               return TNS_ERR_MAX_LIMIT;
+       }
+       evif_dat.insert_ptr0 = 0xFFFF;
+       evif_dat.insert_ptr1 = 0xFFFF;
+       evif_dat.insert_ptr2 = 0xFFFF;
+       evif_dat.mre_ptr = 0x7FFF;
+       evif_dat.rewrite_ptr0 = 0xFF;
+       evif_dat.rewrite_ptr1 = 0xFF;
+       evif_dat.data31_0 = 0x0;
+       evif_dat.q_mirror_en = 0x0;
+       evif_dat.mirror_en = 0x0;
+       evif_dat.mtu_prf = 0x0;
+       evif_dat.truncate = 0x0;
+       evif_dat.rsp_type = 0x3;
+       disable_all_ports(&evif_dat);
+       for (j = 0; j < VALID_MCAST_PROMIS(node, ing_grp); j++)
+               enable_port(MCAST_PROMIS(node, ing_grp, j), &evif_dat);
+       enable_port(vf, &evif_dat);
+       ret = tbl_write(node, MAC_EVIF_TABLE, vif, NULL, NULL, &evif_dat);
+       if (ret)
+               return ret;
+       data.data = 0x0ull;
+       data.s.evif = vif;
+       ret = tbl_write(node, MAC_FILTER_TABLE, mac_idx, &key, &mask, &data);
+       if (ret)
+               return ret;
+       macfilter_freeindex[node] += 1;
+       registered_vf_filter_index(node, vf, mac_idx, 1);
+
+       return TNS_NO_ERR;
+}
+
+int del_mac_filter_entry(int node, int table_id, int vf, int mac_idx,
+                        void *mac_DA, int addr_type)
+{
+       int ret;
+       struct mac_filter_entry tbl_entry;
+       int old_mac_idx = -1, vif;
+       int j, k;
+
+       tbl_entry.key.is_valid = 1;
+       tbl_entry.key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       tbl_entry.mask.key_type.s.ingress_grp = 0x0;
+
+       for (j = 5, k = 0; j >= 0; j--, k++) {
+               tbl_entry.key.key_type.s.mac_DA[k] = ((u8 *)mac_DA)[j];
+               tbl_entry.mask.key_type.s.mac_DA[k] = 0x0;
+       }
+
+       ret = filter_tbl_lookup(node, MAC_FILTER_TABLE, (void *)&tbl_entry,
+                               &old_mac_idx);
+       if (ret)
+               return ret;
+
+       if (old_mac_idx == -1) {
+               filter_dbg(FDEBUG, "Invalid Delete, entry not found\n");
+               return TNS_ERR_ENTRY_NOT_FOUND;
+       }
+       if (mac_idx != -1 && mac_idx != old_mac_idx) {
+               filter_dbg(FDEBUG, "Found and requested are mismatched\n");
+               return TNS_ERR_ENTRY_NOT_FOUND;
+       }
+       if (old_mac_idx == vf) {
+               filter_dbg(FDEBUG, "Primary Unicast MAC delete not allowed\n");
+               return TNS_ERR_MAC_FILTER_INVALID_ENTRY;
+       }
+
+       //Remove MAC Filter entry from VF register MAC filter list
+       registered_vf_filter_index(node, vf, old_mac_idx, 0);
+
+       //Remove VIF entry (output portmask) related to this filter entry
+       vif = tbl_entry.data.s.evif;
+       if (addr_type) {
+               struct evif_entry evif_dat;
+
+               ret = tbl_read(node, MAC_EVIF_TABLE, vif, NULL, NULL,
+                              &evif_dat);
+               if (ret)
+                       return ret;
+
+               disable_port(vf, &evif_dat);
+               ret = tbl_write(node, MAC_EVIF_TABLE, vif, NULL, NULL,
+                               &evif_dat);
+               if (ret)
+                       return ret;
+
+               dump_evif_entry(&evif_dat);
+               //In case of multicast MAC check for empty portmask
+               if (!is_empty_vif(node, vf, &evif_dat))
+                       return TNS_NO_ERR;
+       }
+       invalidate_table_entry(node, MAC_FILTER_TABLE, old_mac_idx);
+       free_table_index(node, MAC_FILTER_TABLE, old_mac_idx);
+       free_table_index(node, MAC_EVIF_TABLE, vif);
+       macfilter_freeindex[node] -= 1;
+
+       return TNS_NO_ERR;
+}
+
+int add_mac_filter_entry(int node, int table_id, int vf, int mac_idx,
+                        void *mac_DA)
+{
+       int ret;
+       struct mac_filter_entry tbl_entry;
+       int old_mac_idx = -1;
+       int j, k;
+       struct mac_filter_keymask_s key, mask;
+       union mac_filter_data_s data;
+
+       /* We are restricting each VF to register atmost 11 filter entries
+        * (including unicast & multicast)
+        */
+       if (mac_idx != vf &&
+           vf_reg_data[node][vf].filter_count >= TNS_MAX_MAC_PER_VF) {
+               if (!vf_reg_data[node][vf].vf_in_mcast_promis) {
+                       tns_enable_mcast_promis(node, vf);
+                       vf_reg_data[node][vf].vf_in_mcast_promis = 1;
+               }
+               return TNS_ERR_MAX_LIMIT;
+       }
+
+       //Adding Multicast MAC will be handled differently
+       if ((((u8 *)mac_DA)[0]) & 0x1) {
+               filter_dbg(FDEBUG, "%s It is multicast MAC entry\n", __func__);
+               return add_mac_filter_mcast_entry(node, table_id, vf, mac_idx,
+                                                 mac_DA);
+       }
+
+       tbl_entry.key.is_valid = 1;
+       tbl_entry.key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       tbl_entry.mask.key_type.s.ingress_grp = 0x0;
+       for (j = 5, k = 0; j >= 0; j--, k++) {
+               tbl_entry.key.key_type.s.mac_DA[k] = ((u8 *)mac_DA)[j];
+               tbl_entry.mask.key_type.s.mac_DA[k] = 0x0;
+       }
+       ret = filter_tbl_lookup(node, MAC_FILTER_TABLE, (void *)&tbl_entry,
+                               &old_mac_idx);
+       if (ret)
+               return ret;
+       if (old_mac_idx != -1) {
+               filter_dbg(FINFO, "Duplicate entry found at %d\n", old_mac_idx);
+               if (tbl_entry.data.s.evif != vf) {
+                       filter_dbg(FDEBUG, "Registered VF %d Requested VF %d\n",
+                                  (int)tbl_entry.data.s.evif, (int)vf);
+                       return TNS_ERR_DUPLICATE_MAC;
+               }
+               return TNS_NO_ERR;
+       }
+       if (alloc_table_index(node, MAC_FILTER_TABLE, &mac_idx)) {
+               filter_dbg(FERR, "(%s) Filter Table Full\n", __func__);
+               return TNS_ERR_MAX_LIMIT;
+       }
+       if (mac_idx == -1) {
+               filter_dbg(FERR, "!!!ERROR!!! reached maximum limit\n");
+               return TNS_ERR_MAX_LIMIT;
+       }
+       key.is_valid = 1;
+       mask.is_valid = 1;
+       key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       mask.key_type.s.ingress_grp = 0;
+       for (j = 5, k = 0; j >= 0; j--, k++) {
+               key.key_type.s.mac_DA[k] = ((u8 *)mac_DA)[j];
+               mask.key_type.s.mac_DA[k] = 0x0;
+       }
+       filter_dbg(FINFO, "VF id: %d with ingress_grp: %d ", vf,
+                  key.key_type.s.ingress_grp);
+       filter_dbg(FINFO, "MAC: %x: %x: %x %x: %x %x Added at Index: %d\n",
+                  ((u8 *)mac_DA)[0], ((u8 *)mac_DA)[1],
+                  ((u8 *)mac_DA)[2], ((u8 *)mac_DA)[3],
+                  ((u8 *)mac_DA)[4], ((u8 *)mac_DA)[5], mac_idx);
+
+       data.data = 0x0ull;
+       data.s.evif = vf;
+       ret = tbl_write(node, MAC_FILTER_TABLE, mac_idx, &key, &mask, &data);
+       if (ret)
+               return ret;
+
+       if (mac_idx != vf) {
+               registered_vf_filter_index(node, vf, mac_idx, 1);
+               macfilter_freeindex[node] += 1;
+       }
+
+       return TNS_NO_ERR;
+}
+
+int vf_interface_up(int node, int tbl_id, int vf, void *mac_DA)
+{
+       int ret;
+
+       //Enable unicast MAC entry for this VF
+       ret = add_mac_filter_entry(node, tbl_id, vf, vf, mac_DA);
+       if (ret)
+               return ret;
+
+       return TNS_NO_ERR;
+}
+
+int del_vlan_entry(int node, int vf, int vlan, int vlanx)
+{
+       int ret;
+       struct vlan_filter_entry tbl_entry;
+       int vlan_tbl_idx = -1, i;
+       vlan_port_bitmap_t vlan_vif;
+       int vlan_cnt = vf_reg_data[node][vf].vlan_count;
+
+       tbl_entry.key.is_valid = 1;
+       tbl_entry.key.key_type.key_value  = 0x0ull;
+       tbl_entry.mask.key_type.key_value = 0xFFFFFFFFFFFFFFFFull;
+       tbl_entry.key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       tbl_entry.mask.key_type.s.ingress_grp = 0x0;
+       tbl_entry.key.key_type.s.vlan = vlan;
+       tbl_entry.mask.key_type.s.vlan = 0x0;
+
+       filter_dbg(FINFO, "%s VF %d with ingress_grp %d VLANID %d\n",
+                  __func__, vf, tbl_entry.key.key_type.s.ingress_grp,
+                  tbl_entry.key.key_type.s.vlan);
+
+       ret = filter_tbl_lookup(node, VLAN_FILTER_TABLE, &tbl_entry,
+                               &vlan_tbl_idx);
+       if (ret)
+               return ret;
+
+       if (vlan_tbl_idx == -1) {
+               filter_dbg(FINFO, "VF %d VLAN %d filter not registered\n",
+                          vf, vlan);
+               return TNS_NO_ERR;
+       }
+
+       if (vlan_tbl_idx < 1 && vlan_tbl_idx >= TNS_VLAN_FILTER_MAX_INDEX) {
+               filter_dbg(FERR, "Invalid VLAN Idx: %d\n", vlan_tbl_idx);
+               return TNS_ERR_VLAN_FILTER_INVLAID_ENTRY;
+       }
+
+       vlanx = tbl_entry.data.s.filter_idx;
+       ret = tbl_read(node, VLAN_EVIF_TABLE, vlanx, NULL, NULL,
+                      (void *)(&vlan_vif[0]));
+       if (ret)
+               return ret;
+
+       disable_vlan_port(vf, vlan_vif);
+       ret = tbl_write(node, VLAN_EVIF_TABLE, vlanx, NULL, NULL,
+                       (void *)(&vlan_vif[0]));
+       if (ret)
+               return ret;
+
+       for (i = 0; i < vlan_cnt; i++) {
+               if (vf_reg_data[node][vf].vlan[i] == vlan) {
+                       int j;
+
+                       for (j = i; j < vlan_cnt - 1; j++)
+                               vf_reg_data[node][vf].vlan[j] =
+                                vf_reg_data[node][vf].vlan[j + 1];
+                       vf_reg_data[node][vf].vlan_count -= 1;
+                       break;
+               }
+       }
+       if (is_empty_vlan(node, vf, vlan, vlan_vif)) {
+               free_table_index(node, VLAN_FILTER_TABLE, vlanx);
+               vlanfilter_freeindex[node] -= 1;
+               invalidate_table_entry(node, VLAN_FILTER_TABLE, vlanx);
+       }
+
+       return TNS_NO_ERR;
+}
+
+int add_vlan_entry(int node, int vf, int vlan, int vlanx)
+{
+       int ret;
+       int pf_vf;
+       struct vlan_filter_entry tbl_entry;
+       int vlan_tbl_idx = -1;
+       vlan_port_bitmap_t vlan_vif;
+
+       if (vf_reg_data[node][vf].vlan_count >= TNS_MAX_VLAN_PER_VF) {
+               filter_dbg(FDEBUG, "Reached maximum limit per VF count: %d\n",
+                          vf_reg_data[node][vf].vlan_count);
+               return TNS_ERR_MAX_LIMIT;
+       }
+
+       tbl_entry.key.is_valid = 1;
+       tbl_entry.key.key_type.key_value  = 0x0ull;
+       tbl_entry.mask.key_type.key_value = 0xFFFFFFFFFFFFFFFFull;
+       tbl_entry.key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       tbl_entry.mask.key_type.s.ingress_grp = 0x0;
+       tbl_entry.key.key_type.s.vlan = vlan;
+       tbl_entry.mask.key_type.s.vlan = 0x0;
+
+       ret = filter_tbl_lookup(node, VLAN_FILTER_TABLE, &tbl_entry,
+                               &vlan_tbl_idx);
+       if (ret)
+               return ret;
+
+       if (vlan_tbl_idx != -1) {
+               filter_dbg(FINFO, "Duplicate entry found at %d\n",
+                          vlan_tbl_idx);
+               if (vlan_tbl_idx < 1 &&
+                   vlan_tbl_idx >= TNS_VLAN_FILTER_MAX_INDEX) {
+                       filter_dbg(FDEBUG, "Invalid VLAN Idx %d\n",
+                                  vlan_tbl_idx);
+                       return TNS_ERR_VLAN_FILTER_INVLAID_ENTRY;
+               }
+
+               vlanx = tbl_entry.data.s.filter_idx;
+               ret = tbl_read(node, VLAN_EVIF_TABLE, vlanx, NULL, NULL,
+                              (void *)(&vlan_vif[0]));
+               if (ret)
+                       return ret;
+
+               enable_vlan_port(vf, vlan_vif);
+               ret = tbl_write(node, VLAN_EVIF_TABLE, vlanx, NULL, NULL,
+                               (void *)(&vlan_vif[0]));
+               if (ret)
+                       return ret;
+
+               vf_reg_data[node][vf].vlan[vf_reg_data[node][vf].vlan_count] =
+                vlan;
+               vf_reg_data[node][vf].vlan_count += 1;
+
+               return TNS_NO_ERR;
+       }
+
+       if (alloc_table_index(node, VLAN_FILTER_TABLE, &vlanx)) {
+               filter_dbg(FDEBUG, "%s VLAN Filter Table Full\n", __func__);
+               return TNS_ERR_MAX_LIMIT;
+       }
+       disable_vlan_vif_ports(vlan_vif);
+       enable_vlan_port(vf, vlan_vif);
+       enable_vlan_port(intr_to_ingressgrp[node][vf], vlan_vif);
+       ret = vf_pfvf_id(node, vf, &pf_vf);
+
+       if (ret)
+               return ret;
+
+       if (vf_reg_data[node][pf_vf].vf_in_promis)
+               enable_vlan_port(pf_vf, vlan_vif);
+
+       dump_vlan_vif_portss(vlan_vif);
+       ret = tbl_write(node, VLAN_EVIF_TABLE, vlanx, NULL, NULL,
+                       (void *)(&vlan_vif[0]));
+       if (ret)
+               return ret;
+
+       tbl_entry.key.is_valid = 1;
+       tbl_entry.key.key_type.s.ingress_grp = intr_to_ingressgrp[node][vf];
+       tbl_entry.key.key_type.s.vlan = vlan;
+       tbl_entry.key.key_type.s.reserved = 0x0;
+       tbl_entry.key.key_type.s.reserved1 = 0x0;
+       tbl_entry.mask.is_valid = 1;
+       tbl_entry.mask.key_type.s.ingress_grp = 0x0;
+       tbl_entry.mask.key_type.s.vlan = 0x0;
+       tbl_entry.mask.key_type.s.reserved = 0xF;
+       tbl_entry.mask.key_type.s.reserved1 = 0xFFFFFFFF;
+       tbl_entry.data.data = 0x0ull;
+       tbl_entry.data.s.filter_idx = vlanx;
+       ret = tbl_write(node, VLAN_FILTER_TABLE, vlanx, &tbl_entry.key,
+                       &tbl_entry.mask, &tbl_entry.data);
+       if (ret)
+               return ret;
+
+       filter_dbg(FINFO, "VF %d with ingress_grp %d VLAN %d Added at %d\n",
+                  vf, tbl_entry.key.key_type.s.ingress_grp,
+                  tbl_entry.key.key_type.s.vlan, vlanx);
+
+       vlanfilter_freeindex[node] += 1;
+       vf_reg_data[node][vf].vlan[vf_reg_data[node][vf].vlan_count] = vlan;
+       vf_reg_data[node][vf].vlan_count += 1;
+
+       return TNS_NO_ERR;
+}
+
+int enable_promiscuous_mode(int node, int vf)
+{
+       int ret = tns_enable_mcast_promis(node, vf);
+       int pf_vf;
+
+       if (ret)
+               return ret;
+
+       vf_reg_data[node][vf].vf_in_promis = 1;
+       ret = vf_pfvf_id(node, vf, &pf_vf);
+       if (ret)
+               return ret;
+
+       if (vf == pf_vf) {
+               //PFVF interface, enable full promiscuous mode
+               int i;
+               int vif = intr_to_ingressgrp[node][vf];
+               struct evif_entry evif_dat;
+               struct itt_entry_s port_cfg_entry;
+
+               for (i = 0; i < macfilter_freeindex[node]; i++) {
+                       struct mac_filter_entry tbl_entry;
+
+                       ret = tbl_read(node, MAC_FILTER_TABLE, i,
+                                      &tbl_entry.key, &tbl_entry.mask,
+                                      &tbl_entry.data);
+                       if (ret && (ret != TNS_ERR_MAC_FILTER_INVALID_ENTRY))
+                               return ret;
+                       else if (ret == TNS_ERR_MAC_FILTER_INVALID_ENTRY)
+                               continue;
+
+                       if (tbl_entry.key.key_type.s.ingress_grp ==
+                           intr_to_ingressgrp[node][vf]) {
+                               int vif = tbl_entry.data.s.evif;
+                               struct evif_entry evif_dat;
+
+                               ret = tbl_read(node, MAC_EVIF_TABLE, vif, NULL,
+                                              NULL, &evif_dat);
+                               if (ret)
+                                       return ret;
+
+                               enable_port(vf, &evif_dat);
+                               dump_evif_entry(&evif_dat);
+                               ret = tbl_write(node, MAC_EVIF_TABLE, vif, NULL,
+                                               NULL, (void *)&evif_dat);
+                               if (ret)
+                                       return ret;
+                       }
+               }
+               /*If pfVf interface enters in promiscuous mode we will forward
+                * packets destined to corresponding LMAC
+                */
+
+               ret = tbl_read(node, MAC_EVIF_TABLE, vif, NULL, NULL,
+                              &evif_dat);
+               if (ret)
+                       return ret;
+               enable_port(vf, &evif_dat);
+               dump_evif_entry(&evif_dat);
+               ret = tbl_write(node, MAC_EVIF_TABLE, vif, NULL, NULL,
+                               (void *)&evif_dat);
+               if (ret)
+                       return ret;
+
+               /* Update default_evif of LMAC from NULLVif to pfVf interface,
+                * so that pfVf will shows all dropped packets as well
+                */
+               ret = tbl_read(node, PORT_CONFIG_TABLE,
+                              intr_to_ingressgrp[node][vf], NULL, NULL,
+                              &port_cfg_entry);
+               if (ret)
+                       return ret;
+
+               port_cfg_entry.default_evif = vf;
+               ret = tbl_write(node, PORT_CONFIG_TABLE,
+                               intr_to_ingressgrp[node][vf], NULL, NULL,
+                               (void *)&port_cfg_entry);
+               if (ret)
+                       return ret;
+
+               filter_dbg(FINFO, "%s Port %d pkt_dir %d defaultVif %d",
+                          __func__, vf, port_cfg_entry.pkt_dir,
+                          port_cfg_entry.default_evif);
+               filter_dbg(FINFO, " adminVlan %d %s\n",
+                          port_cfg_entry.admin_vlan,
+                          port_cfg_entry.is_admin_vlan_enabled ? "Enable" :
+                               "Disable");
+
+               for (i = 1; i < vlanfilter_freeindex[node]; i++) {
+                       struct vlan_filter_entry tbl_entry;
+
+                       ret = tbl_read(node, VLAN_FILTER_TABLE, i,
+                                      &tbl_entry.key, &tbl_entry.mask,
+                                      &tbl_entry.data);
+                       if (ret && (ret != TNS_ERR_MAC_FILTER_INVALID_ENTRY))
+                               return ret;
+                       else if (ret == TNS_ERR_MAC_FILTER_INVALID_ENTRY)
+                               continue;
+
+                       if (tbl_entry.key.key_type.s.ingress_grp ==
+                           intr_to_ingressgrp[node][vf]) {
+                               int vlanx = tbl_entry.data.s.filter_idx;
+                               vlan_port_bitmap_t vlan_vif;
+
+                               ret = tbl_read(node, VLAN_EVIF_TABLE, vlanx,
+                                              NULL, NULL,
+                                              (void *)(&vlan_vif[0]));
+                               if (ret)
+                                       return ret;
+                               enable_vlan_port(vf, vlan_vif);
+                               ret = tbl_write(node, VLAN_EVIF_TABLE, vlanx,
+                                               NULL, NULL,
+                                               (void *)(&vlan_vif[0]));
+                               if (ret)
+                                       return ret;
+                       }
+               }
+       } else {
+               //VF interface enable multicast promiscuous mode
+               int i;
+               int ret;
+
+               for (i = TNS_MAX_VF; i < macfilter_freeindex[node]; i++) {
+                       struct mac_filter_entry tbl_entry;
+
+                       ret = tbl_read(node, MAC_FILTER_TABLE, i,
+                                      &tbl_entry.key, &tbl_entry.mask,
+                                      &tbl_entry.data);
+                       if (ret && (ret != TNS_ERR_MAC_FILTER_INVALID_ENTRY))
+                               return ret;
+                       else if (ret == TNS_ERR_MAC_FILTER_INVALID_ENTRY)
+                               continue;
+
+                       /* We found filter entry, lets verify either this is
+                        * unicast or multicast
+                        */
+                       if (((((u8 *)tbl_entry.key.key_type.s.mac_DA)[5]) &
+                              0x1) && (tbl_entry.key.key_type.s.ingress_grp ==
+                                       intr_to_ingressgrp[node][vf])) {
+                               int vif = tbl_entry.data.s.evif;
+                               struct evif_entry evif_dat;
+
+                               ret = tbl_read(node, MAC_EVIF_TABLE, vif, NULL,
+                                              NULL, &evif_dat);
+                               if (ret)
+                                       return ret;
+                               enable_port(vf, &evif_dat);
+                               dump_evif_entry(&evif_dat);
+                               ret = tbl_write(node, MAC_EVIF_TABLE, vif, NULL,
+                                               NULL, (void *)&evif_dat);
+                               if (ret)
+                                       return ret;
+                       }
+               }
+       }
+
+       return TNS_NO_ERR;
+}
+
+int disable_promiscuous_mode(int node, int vf)
+{
+       int i, pf_vf;
+       int ret;
+
+       vf_reg_data[node][vf].vf_in_promis = 0;
+       ret = vf_pfvf_id(node, vf, &pf_vf);
+       if (ret)
+               return ret;
+
+       for (i = TNS_MAX_VF; i < macfilter_freeindex[node]; i++) {
+               struct mac_filter_entry tbl_entry;
+
+               ret = tbl_read(node, MAC_FILTER_TABLE, i, &tbl_entry.key,
+                              &tbl_entry.mask, &tbl_entry.data);
+               if (ret && (ret != TNS_ERR_MAC_FILTER_INVALID_ENTRY))
+                       return ret;
+               else if (ret == TNS_ERR_MAC_FILTER_INVALID_ENTRY)
+                       continue;
+
+               //We found an entry belongs to this group
+               if (tbl_entry.key.key_type.s.ingress_grp ==
+                   intr_to_ingressgrp[node][vf]) {
+                       int vif = tbl_entry.data.s.evif;
+                       struct evif_entry evif_dat;
+
+                       if (is_vf_registered_entry(node, vf, i))
+                               continue;
+
+                       //Is this multicast entry
+                       if (((((u8 *)tbl_entry.key.key_type.s.mac_DA)[5]) &
+                              0x1) && vf_reg_data[node][vf].vf_in_mcast_promis)
+                               continue;
+
+                       //Disable port bitmap in EVIF entry
+                       ret = tbl_read(node, MAC_EVIF_TABLE, vif, NULL,
+                                      NULL, &evif_dat);
+                       if (ret)
+                               return ret;
+                       disable_port(vf, &evif_dat);
+                       dump_evif_entry(&evif_dat);
+                       ret = tbl_write(node, MAC_EVIF_TABLE, vif, NULL, NULL,
+                                       (void *)&evif_dat);
+                       if (ret)
+                               return ret;
+               }
+       }
+       /* If pfVf interface exit from promiscuous mode, then  we will change
+        * portbitmap corresponding to LMAC
+        */
+       if (vf == pf_vf) {
+               int vif = intr_to_ingressgrp[node][vf];
+               struct evif_entry evif_dat;
+               struct itt_entry_s port_cfg_entry;
+
+               ret = tbl_read(node, MAC_EVIF_TABLE, vif, NULL, NULL,
+                              &evif_dat);
+               if (ret)
+                       return ret;
+
+               disable_port(vf, &evif_dat);
+               dump_evif_entry(&evif_dat);
+               ret = tbl_write(node, MAC_EVIF_TABLE, vif, NULL, NULL,
+                               (void *)&evif_dat);
+               if (ret)
+                       return ret;
+
+               for (i = 1; i < vlanfilter_freeindex[node]; i++) {
+                       struct vlan_filter_entry tbl_entry;
+
+                       ret = tbl_read(node, VLAN_FILTER_TABLE, i,
+                                      &tbl_entry.key, &tbl_entry.mask,
+                                      &tbl_entry.data);
+                       if (ret && (ret != TNS_ERR_MAC_FILTER_INVALID_ENTRY))
+                               return ret;
+                       else if (ret == TNS_ERR_MAC_FILTER_INVALID_ENTRY)
+                               continue;
+
+                       if (tbl_entry.key.key_type.s.ingress_grp ==
+                           intr_to_ingressgrp[node][vf]) {
+                               int vlanx = tbl_entry.data.s.filter_idx;
+                               vlan_port_bitmap_t vlan_vif;
+                               int vlan = tbl_entry.key.key_type.s.vlan;
+
+                               if (!is_vlan_registered(node, vf, vlan)) {
+                                       ret = tbl_read(node, VLAN_EVIF_TABLE,
+                                                      vlanx, NULL, NULL,
+                                                      (void *)(&vlan_vif[0]));
+                                       if (ret)
+                                               return ret;
+                                       disable_vlan_port(vf, vlan_vif);
+                                       ret = tbl_write(node, VLAN_EVIF_TABLE,
+                                                       vlanx, NULL, NULL,
+                                                       (void *)(&vlan_vif[0]));
+                                       if (ret)
+                                               return ret;
+                               }
+                       }
+               }
+               //Update default_evif of LMAC to NULLVif
+               ret = tbl_read(node, PORT_CONFIG_TABLE,
+                              intr_to_ingressgrp[node][vf], NULL, NULL,
+                              &port_cfg_entry);
+               if (ret)
+                       return ret;
+
+               port_cfg_entry.default_evif = TNS_NULL_VIF;
+               ret = tbl_write(node, PORT_CONFIG_TABLE,
+                               intr_to_ingressgrp[node][vf], NULL, NULL,
+                               (void *)&port_cfg_entry);
+               if (ret)
+                       return ret;
+               filter_dbg(FINFO, "%s Port %d pkt_dir %d defaultVif %d ",
+                          __func__, vf, port_cfg_entry.pkt_dir,
+                          port_cfg_entry.default_evif);
+               filter_dbg(FINFO, "adminVlan %d %s\n",
+                          port_cfg_entry.admin_vlan,
+                          port_cfg_entry.is_admin_vlan_enabled ? "Enable" :
+                          "Disable");
+       }
+       if (!vf_reg_data[node][vf].vf_in_mcast_promis)
+               remove_vf_from_mcast_promis_grp(node, vf);
+
+       return TNS_NO_ERR;
+}
+
+/* CRB-1S configuration
+ * Valid LMAC's - 3 (128, 132, & 133)
+ * PFVF - 3 (0, 64, & 96)
+ * bcast_vif - 3 (136, 140, & 141)
+ * mcast_vif - 3 (144, 148, & 149)
+ * null_vif - 1 (152)
+ */
+int mac_filter_config(void)
+{
+       int node, j;
+
+       for (node = 0; node < nr_node_ids; node++) {
+               int lmac;
+
+               //Reset inerface to Ingress Group
+               for (j = 0; j < TNS_MAC_FILTER_MAX_SYS_PORTS; j++)
+                       intr_to_ingressgrp[node][j] = j;
+
+               if (!pf_vf_map_data[node].valid)
+                       continue;
+
+               for (j = 0; j < TNS_MAX_INGRESS_GROUP; j++)
+                       ingressgrp_gblvif[node][j].is_valid = 0;
+
+               for (lmac = 0; lmac < pf_vf_map_data[node].lmac_cnt; lmac++) {
+                       int slm = pf_vf_map_data[node].pf_vf[lmac].sys_lmac;
+                       int valid_pf = pf_vf_map_data[node].pf_vf[lmac].pf_id;
+                       int num_vfs = pf_vf_map_data[node].pf_vf[lmac].num_vfs;
+                       struct evif_entry evif_dat;
+                       int bvif, mvif;
+                       int ret;
+
+                       bvif = TNS_BASE_BCAST_VIF + slm;
+                       mvif = TNS_BASE_MCAST_VIF + slm;
+
+                       //Map inerface to Ingress Group
+                       for (j = valid_pf; j < (valid_pf + num_vfs); j++) {
+                               struct itt_entry_s port_cfg_entry;
+                               int ret;
+
+                               intr_to_ingressgrp[node][j] = TNS_MAX_VF + slm;
+
+                               ret = tbl_read(node, PORT_CONFIG_TABLE, j, NULL,
+                                              NULL, (void *)&port_cfg_entry);
+                               if (ret)
+                                       return ret;
+                               port_cfg_entry.default_evif =
+                                       intr_to_ingressgrp[node][j];
+                               ret = tbl_write(node, PORT_CONFIG_TABLE, j,
+                                               NULL, NULL,
+                                               (void *)&port_cfg_entry);
+                               if (ret)
+                                       return ret;
+                       }
+
+                       //LMAC Configuration
+                       ingressgrp_gblvif[node][slm].is_valid = 1;
+                       ingressgrp_gblvif[node][slm].ingress_grp = TNS_MAX_VF +
+                                                                    slm;
+                       ingressgrp_gblvif[node][slm].pf_vf = valid_pf;
+                       ingressgrp_gblvif[node][slm].bcast_vif = bvif;
+                       ingressgrp_gblvif[node][slm].mcast_vif = mvif;
+                       ingressgrp_gblvif[node][slm].null_vif = TNS_NULL_VIF;
+                       MCAST_PROMIS(node, slm, 0) = TNS_MAX_VF + slm;
+                       VALID_MCAST_PROMIS(node, slm) = 1;
+
+                       filter_dbg(FINFO, "lmac %d syslm %d num_vfs %d ",
+                                  lmac, slm,
+                                  pf_vf_map_data[node].pf_vf[lmac].num_vfs);
+                       filter_dbg(FINFO, "ingress_grp %d pfVf %d bCast %d ",
+                                  ingressgrp_gblvif[node][slm].ingress_grp,
+                                  ingressgrp_gblvif[node][slm].pf_vf,
+                                  ingressgrp_gblvif[node][slm].bcast_vif);
+                       filter_dbg(FINFO, "mCast: %d\n",
+                                  ingressgrp_gblvif[node][slm].mcast_vif);
+
+                       ret = tbl_read(node, MAC_EVIF_TABLE, bvif, NULL, NULL,
+                                      &evif_dat);
+                       if (ret)
+                               return ret;
+
+                       evif_dat.rewrite_ptr0 = 0xFF;
+                       evif_dat.rewrite_ptr1 = 0xFF;
+                       enable_port(ingressgrp_gblvif[node][slm].ingress_grp,
+                                   &evif_dat);
+
+                       ret = tbl_write(node, MAC_EVIF_TABLE, bvif, NULL, NULL,
+                                       (void *)&evif_dat);
+                       if (ret)
+                               return ret;
+
+                       ret = tbl_read(node, MAC_EVIF_TABLE, mvif, NULL, NULL,
+                                      &evif_dat);
+                       if (ret)
+                               return ret;
+
+                       evif_dat.rewrite_ptr0 = 0xFF;
+                       evif_dat.rewrite_ptr1 = 0xFF;
+                       enable_port(ingressgrp_gblvif[node][slm].ingress_grp,
+                                   &evif_dat);
+
+                       ret = tbl_write(node, MAC_EVIF_TABLE, mvif, NULL, NULL,
+                                       (void *)&evif_dat);
+                       if (ret)
+                               return ret;
+
+                       ret = tbl_read(node, MAC_EVIF_TABLE, TNS_NULL_VIF, NULL,
+                                      NULL, &evif_dat);
+                       if (ret)
+                               return ret;
+
+                       evif_dat.rewrite_ptr0 = 0xFF;
+                       evif_dat.rewrite_ptr1 = 0xFF;
+
+                       ret = tbl_write(node, MAC_EVIF_TABLE, TNS_NULL_VIF,
+                                       NULL, NULL, (void *)&evif_dat);
+                       if (ret)
+                               return ret;
+               }
+               j = 0;
+               alloc_table_index(node, VLAN_FILTER_TABLE, &j);
+
+               for (j = 0; j < TNS_MAX_VF; j++) {
+                       vf_reg_data[node][j].vf_in_mcast_promis = 0;
+                       vf_reg_data[node][j].filter_count = 1;
+                       vf_reg_data[node][j].filter_index[0] = j;
+                       vf_reg_data[node][j].vlan_count = 0;
+                       alloc_table_index(node, MAC_FILTER_TABLE, &j);
+               }
+               for (j = 0; j <= TNS_NULL_VIF; j++)
+                       alloc_table_index(node, MAC_EVIF_TABLE, &j);
+               macfilter_freeindex[node] = TNS_MAX_VF;
+               vlanfilter_freeindex[node] = 1;
+       }
+
+       return TNS_NO_ERR;
+}
+
+int add_admin_vlan(int node, int vf, int vlan)
+{
+       int index = -1;
+       int ret;
+       struct itt_entry_s port_cfg_entry;
+
+       ret = add_vlan_entry(node, vf, vlan, index);
+       if (ret) {
+               filter_dbg(FERR, "Add admin VLAN for VF: %d Failed %d\n",
+                          vf, ret);
+               return ret;
+       }
+
+       ret = tbl_read(node, PORT_CONFIG_TABLE, vf, NULL, NULL,
+                      (void *)&port_cfg_entry);
+       if (ret)
+               return ret;
+       port_cfg_entry.is_admin_vlan_enabled = 1;
+       port_cfg_entry.admin_vlan = vlan;
+       ret = tbl_write(node, PORT_CONFIG_TABLE, vf, NULL, NULL,
+                       (void *)&port_cfg_entry);
+       if (ret)
+               return ret;
+       filter_dbg(FINFO, "%s Port %d dir %d defaultVif %d adminVlan %d %s\n",
+                  __func__, vf, port_cfg_entry.pkt_dir,
+                  port_cfg_entry.default_evif, port_cfg_entry.admin_vlan,
+                  port_cfg_entry.is_admin_vlan_enabled ? "Enable" : "Disable");
+
+       return TNS_NO_ERR;
+}
+
+int del_admin_vlan(int node, int vf, int vlan)
+{
+       int index = -1;
+       int ret;
+       struct itt_entry_s port_cfg_entry;
+
+       ret = del_vlan_entry(node, vf, vlan, index);
+       if (ret) {
+               filter_dbg(FERR, "Delete admin VLAN: %d for VF %d failed %d\n",
+                          vlan, vf, ret);
+               return ret;
+       }
+
+       ret = tbl_read(node, PORT_CONFIG_TABLE, vf, NULL, NULL,
+                      (void *)&port_cfg_entry);
+       if (ret)
+               return ret;
+       port_cfg_entry.is_admin_vlan_enabled = 0;
+       port_cfg_entry.admin_vlan = 0x0;
+       ret = tbl_write(node, PORT_CONFIG_TABLE, vf, NULL, NULL,
+                       (void *)&port_cfg_entry);
+       if (ret)
+               return ret;
+       filter_dbg(FINFO, "%s Port %d dir %d defaultVif %d adminVlan %d %s\n",
+                  __func__, vf, port_cfg_entry.pkt_dir,
+                  port_cfg_entry.default_evif, port_cfg_entry.admin_vlan,
+                  port_cfg_entry.is_admin_vlan_enabled ? "Enable" : "Disable");
+
+       return TNS_NO_ERR;
+}
+
+void link_status_notification(int node, int vf, void *arg)
+{
+       int status =  *((int *)arg);
+       int bcast_vif;
+       int ret;
+       struct evif_entry evif_dat;
+
+       filter_dbg(FINFO, "VF %d Link %s\n", vf, status ? "up " : "down");
+       if (status) {
+               ret = vf_bcast_vif(node, vf, &bcast_vif);
+               if (ret)
+                       return;
+
+               ret = tbl_read(node, MAC_EVIF_TABLE, bcast_vif, NULL, NULL,
+                              &evif_dat);
+               if (ret)
+                       return;
+
+               enable_port(vf, &evif_dat);
+               dump_evif_entry(&evif_dat);
+               ret = tbl_write(node, MAC_EVIF_TABLE, bcast_vif, NULL, NULL,
+                               (void *)&evif_dat);
+               if (ret)
+                       return;
+       } else {
+               ret = vf_bcast_vif(node, vf, &bcast_vif);
+               if (ret)
+                       return;
+
+               ret = tbl_read(node, MAC_EVIF_TABLE, bcast_vif, NULL, NULL,
+                              &evif_dat);
+               if (ret)
+                       return;
+
+               disable_port(vf, &evif_dat);
+               dump_evif_entry(&evif_dat);
+               ret = tbl_write(node, MAC_EVIF_TABLE, bcast_vif, NULL, NULL,
+                               (void *)&evif_dat);
+               if (ret)
+                       return;
+       }
+}
+
+void mac_update_notification(int node, int vf_id, void *arg)
+{
+       u8 *mac = (u8 *)arg;
+
+       filter_dbg(FINFO, "VF:%d MAC %02x:%02x:%02x:%02x:%02x:%02x Updated\n",
+                  vf_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+       vf_interface_up(node, MAC_FILTER_TABLE, vf_id, arg);
+}
+
+void promisc_update_notification(int node, int vf_id, void *arg)
+{
+       int on = *(int *)arg;
+
+       filter_dbg(FERR, "VF %d %s promiscuous mode\n", vf_id,
+                  on ? "enter" : "left");
+       if (on)
+               enable_promiscuous_mode(node, vf_id);
+       else
+               disable_promiscuous_mode(node, vf_id);
+}
+
+void uc_mc_update_notification(int node, int vf_id, void *arg)
+{
+       struct uc_mc_msg *uc_mc_cfg = (struct uc_mc_msg *)arg;
+       u8 *mac;
+
+       mac = (u8 *)uc_mc_cfg->mac_addr;
+       if (uc_mc_cfg->is_flush) {
+               filter_dbg(FINFO, "\nNOTIFICATION VF:%d %s %s\n", vf_id,
+                          uc_mc_cfg->addr_type ? "mc" : "uc", "flush");
+       } else {
+               filter_dbg(FINFO, "\nNOTIFICATION VF:%d %s %s ", vf_id,
+                          uc_mc_cfg->addr_type ? "mc" : "uc",
+                          uc_mc_cfg->is_add ? "add" : "del");
+               filter_dbg(FINFO, "MAC ADDRESS %02x:%02x:%02x:%02x:%02x:%02x\n",
+                          mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+               if (uc_mc_cfg->is_add) {
+                       if (uc_mc_cfg->addr_type)
+                               add_mac_filter_mcast_entry(node,
+                                                          MAC_FILTER_TABLE,
+                                                          vf_id, -1, mac);
+                       else
+                               add_mac_filter_entry(node, MAC_FILTER_TABLE,
+                                                    vf_id, -1, mac);
+               } else {
+                       del_mac_filter_entry(node, MAC_FILTER_TABLE, vf_id, -1,
+                                            mac, uc_mc_cfg->addr_type);
+               }
+       }
+}
+
+void admin_vlan_update_notification(int node, int vf_id, void *arg)
+{
+       struct vlan_msg *vlan_cfg = (struct vlan_msg *)arg;
+
+       filter_dbg(FINFO, "\nNOTIFICATION ADMIN VF %d VLAN id %d %s\n", vf_id,
+                  vlan_cfg->vlan_id, (vlan_cfg->vlan_add) ? "add" : "del");
+       if (vlan_cfg->vlan_add)
+               add_admin_vlan(node, vf_id, vlan_cfg->vlan_id);
+       else
+               del_admin_vlan(node, vf_id, vlan_cfg->vlan_id);
+}
+
+void vlan_update_notification(int node, int vf_id, void *arg)
+{
+       struct vlan_msg *vlan_cfg = (struct vlan_msg *)arg;
+
+       filter_dbg(FINFO, "\nNOTIFICATION VF %d VLAN id %d %s\n", vf_id,
+                  vlan_cfg->vlan_id, (vlan_cfg->vlan_add) ? "add" : "del");
+       if (vlan_cfg->vlan_add && vlan_cfg->vlan_id) {
+               int index = -1;
+               int ret = add_vlan_entry(node, vf_id, vlan_cfg->vlan_id,
+                                             index);
+
+               if (ret)
+                       filter_dbg(FERR, "Adding VLAN failed: %d\n", ret);
+               else
+                       filter_dbg(FINFO, "VF: %d with VLAN: %d added\n",
+                                  vf_id, vlan_cfg->vlan_id);
+       } else if (!vlan_cfg->vlan_add && vlan_cfg->vlan_id) {
+               int index = -1;
+               int ret = del_vlan_entry(node, vf_id, vlan_cfg->vlan_id,
+                                               index);
+
+               if (ret)
+                       filter_dbg(FERR, "Deleting VLAN failed: %d\n", ret);
+               else
+                       filter_dbg(FINFO, "VF: %d with VLAN: %d deleted\n",
+                                  vf_id, vlan_cfg->vlan_id);
+       }
+}
+
+void pf_notify_msg_handler(int node, void *arg)
+{
+       union nic_mbx *mbx = (union nic_mbx *)arg;
+       int status;
+
+       switch (mbx->msg.msg) {
+       case NIC_MBOX_MSG_ADMIN_VLAN:
+               admin_vlan_update_notification(node, mbx->vlan_cfg.vf_id,
+                                              &mbx->vlan_cfg);
+               break;
+       case NIC_MBOX_MSG_VLAN:
+               vlan_update_notification(node, mbx->vlan_cfg.vf_id,
+                                        &mbx->vlan_cfg);
+               break;
+       case NIC_MBOX_MSG_UC_MC:
+               uc_mc_update_notification(node, mbx->vlan_cfg.vf_id,
+                                         &mbx->uc_mc_cfg);
+               break;
+       case NIC_MBOX_MSG_SET_MAC:
+               mac_update_notification(node, mbx->mac.vf_id,
+                                       (void *)mbx->mac.mac_addr);
+               break;
+       case NIC_MBOX_MSG_CFG_DONE:
+       case NIC_MBOX_MSG_OP_UP:
+               status = true;
+               link_status_notification(node, mbx->mac.vf_id, (void *)&status);
+               break;
+       case NIC_MBOX_MSG_SHUTDOWN:
+       case NIC_MBOX_MSG_OP_DOWN:
+               status = false;
+               link_status_notification(node, mbx->mac.vf_id, (void *)&status);
+               break;
+       case NIC_MBOX_MSG_PROMISC:
+               status = mbx->promisc_cfg.on;
+               promisc_update_notification(node, mbx->promisc_cfg.vf_id,
+                                           (void *)&status);
+               break;
+       }
+}
+
+int pf_filter_init(void)
+{
+       mac_filter_config();
+
+       return 0;
+}
-- 
1.8.3.1

Reply via email to