From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757524AbcLUIss (ORCPT ); Wed, 21 Dec 2016 03:48:48 -0500 Received: from mail-bl2nam02on0071.outbound.protection.outlook.com ([104.47.38.71]:13728 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1756711AbcLUIsp (ORCPT ); Wed, 21 Dec 2016 03:48:45 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Satha.Rao@cavium.com; From: Satha Koteswara Rao To: CC: , , , , , , , , , Subject: [RFC PATCH 7/7] Get notifications from PF driver and configure filter block based on request data Date: Wed, 21 Dec 2016 14:16:51 +0530 Message-ID: <1482310011-1862-8-git-send-email-satha.rao@caviumnetworks.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1482310011-1862-1-git-send-email-satha.rao@caviumnetworks.com> References: <1482310011-1862-1-git-send-email-satha.rao@caviumnetworks.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [111.93.218.67] X-ClientProxiedBy: MAXPR01CA0030.INDPRD01.PROD.OUTLOOK.COM (10.164.147.37) To CY4PR07MB2838.namprd07.prod.outlook.com (10.169.252.16) X-MS-Office365-Filtering-Correlation-Id: c5198c68-6e24-402e-4754-08d4297e2ace X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:CY4PR07MB2838; X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB2838;3:H8r1VZ5ORwXjZHOx9p7M7qKGmms5AL7+nRaX3mzsjtD25omCMd/CtFFxssMLwXM1E7JGvG6QM/FliGE2xWG6Eq5Khgv9LilNLP9LPNN4yk1uxIMOtb1QkUZCcHjeimkQdLObYy1ThVP+PUIfqOQ8ps2xpu71rLE+6jenUeWpdzH8gFjTx7PZvhnkMDFw+OVHhs9529Z1Gk86PJ+oUkBWamCW0rnOc6vtgumXL3lgT6GMqIzXZlzCwkGAdqC2NjWhxxVLq1riObhOf/EprzBEEQ== X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB2838;25:dKo6bPrJHruY7TPfk6UnT5tf+Wv5o7qKNF9RzN0FnDU+8xT6wzuGO+GPXf8Wqilq+JoP6iGDZnnO8UlgXmD8C7ZM6sFrkk+bJmKlLn/bhSkDBFc/YSvFPTv6qkOWCzlBXVVIak0PMZ5zbaaaNT4GmuQ3MDrZLhi3RhXaQBBEhq9p+tCWJlK1CJw3g3Bkv7qU3HKbkcZa721lBCDejhazyKqoDGWP96bQjG4WKyiEk1JwfV1qZLtcZFL97p3F3q0eHXdbk806LDyBB2dxkRrJxZUsq6UMqMCJIW+PLKif3yAQ+WEXIog8brbIb89lCb8yhtmoGpwAhMFnN2CI3OehikozmdI9z4+TSTz/8Rw8JeHxD/WXuZSIyIgyoKldhxqW433bg8APVXIFigfz34EJTApQXFCWNF4BwnzccPZHQmhilnwj87p1uZBGtTSP7cV6/hMm8xfrj8Ff/A8G24ym+noFRXqKSxMsEnlOCM6tQcZJyX7iuFcJ26rmKt+SkCMMeHfiiVVEuWi+8mXVNJUa1003HS0pAAhGoq48WiuOPPMS2GYGiVynTgjNZF5ZGYzhhU5162BOpUIBd47Hgw9UbUqcx6EfW5xflgz1gcakCeYeztEWDuxiM7kPoON6rJtJbRQGuw8X6hDRsyvjV8cQu9m5q6tM2+iiZeVvPlP79Hg+JS0iXXKtOtgex8rVeTsuDrHN8lN5GiuBRf7Uq4d2L4iLoNoD0lpAG78jWUTbUQMmiLA5EAw4zqlSMEpaReIHDahSfJ5egdEaV0aiT5m9SCHdRmONkeN7IOyeq82PP+XryiP4Bj96l1z1fEPYLXvHdPXfBd2peYQja7BGC4xnBg== X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB2838;31:Gw+wBfhCQk01sQzbNDmDadN5B9Ra+AFBymj26qn8B5bi6FSc7ievo9ff1WLb7dBtm2+ANHLKVqbP+gLShoBIh1gDSjT6H6PYBdb8P6iVzQ1IOcYLhVviTh7jKzMNCwG7OeoLCQ1mKTfKEskG2KdH4UFqxT/6vMa8JYCQWacMuyu2qMc6ziawlFSLtWaBC/CMLbd3RT7VvqvsrKxowTJL6etLjwmuxsEtOCZpwfxrZw952TaPQUfgYNvoNlBLUy46yoJU9hrsZP63g+nRmoLC6A==;20:wHtgWXBa8wgxhkEvSG/yRf93lSyDLaBP61bNQT7cXAKgMOoSS+pfrnQ5X5rtYWffCm/nd9ZQKfOzGwykY3pWeZ19QxFibcqTg9s4sybdeV3jGyKTZhxAq2f4B6L09AL2csYXMDfWal60CS690++bCYO8n0c0r/0sFPILx2BRd0ICcddhWeJKUr13j+KA0KtfSQYpVYHzUQw1YecNg2f7FZTcNamUPgxw1YsaSaotDFYgrbRIi1RAyaf27zwXzYj0WSS14tg02wvhOHHcSTODnhSbCTuPDyp39IWL3YOe05mGEXGLnQ4P5nd7y3tIUaDNggjbOc1kLBF7vnEvdV5s2T+3Nw9LUsRkRbRiZlEM9jq7JVcJBdZpaJi3HRKgIwCyMdZAAu2nE5DAdN3rMEs+LeTFe+TvXrRFc4EEpHwkG/mni3U5sb6FY+wL/+/qGAiEuNec0aUr98QNxD20pVEpnG4oPdVOgjrhs8f/S7VbWtrabeJcu3lf2Vs2pjMUATQSzVfH46oZIvlUnL0qupGq/Zre/TL3fdBg4Ia28IaQv6apveV/BilSohmhxgG+BiBVEkyZeoHk5dCGUS+56DlY9cgwSYbpg/ujmy2RauBzB3Q= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6041248)(20161123562025)(20161123564025)(20161123560025)(20161123555025)(6072148);SRVR:CY4PR07MB2838;BCL:0;PCL:0;RULEID:;SRVR:CY4PR07MB2838; X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB2838;4:D4WSVbiRb2HYxn9+dKi9rbb93za5gH8JdpFAtxodQ3Iy53clJiEk3kmGq7k6R3rdU8HxBi5ImuJRw2sFZVhH9V9wmyxdmeOiW4QjpGBDluoXSTb/ugqW0ziZHSh8xzUGS88bJqWpFZs3Vzh+4n3RUNTcx1LBvJJGKqXCCKtbxiYv3gFAM6lM8KXKSVY3KupdAywD/S3OXX9jKwBXtN6jkozVnqeo85S+DxjYI3C+oVSfdYRygoQtvkEzbtHgeMiQV9J8GAPsiOtQPgXOt2CqIwE/wra1nWtMAsXput27dhwxdo+QtjXwYDqP8TULMcmeuYlunaOF6oTJxQTSCS4YOosttaoGvOyMIMRbLv1EBNOKFPyN4UkSMxkUqcPyQX/ytP/czlzHJT5SichZ3oGOoh70oZ6co/Y4+VTE116tLYWEfPAZg9qXDbxnBJTVG282IlnQ7J4+FwP7sTvIqTQyMkChoGjgjAEoHw1JA433oTxf43rdLkOOnCPQiLNqU+9dCIKZcixJkgRfEpNAqdBBTMtcxVqAxTlEfO+YTq81AlFaxNo9+QAgtdk+Ewdzs0eF X-Forefront-PRVS: 01630974C0 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6069001)(6009001)(7916002)(39450400003)(189002)(199003)(2906002)(15650500001)(4326007)(101416001)(33646002)(5009440100003)(106356001)(2351001)(68736007)(105586002)(8676002)(50986999)(5003940100001)(53416004)(76506005)(76176999)(48376002)(81156014)(81166006)(42186005)(66066001)(5660300001)(92566002)(50466002)(6506006)(575784001)(110136003)(7736002)(6916009)(47776003)(189998001)(36756003)(6116002)(6666003)(50226002)(3846002)(97736004)(42882006)(25786008)(2950100002)(305945005)(6512006)(69596002)(38730400001)(6486002)(4720700003)(7099028)(2004002)(217873001)(579004);DIR:OUT;SFP:1101;SCL:1;SRVR:CY4PR07MB2838;H:localhost.caveonetworks.com;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY4PR07MB2838;23:3Yo5NyUDkQTfTY5G6OVQlbXX6NEhL2YZKHS6wZ3ll?= =?us-ascii?Q?qSq15C5WynZlhIPBjkx+oVETpTXHqoW0OWH2qaAXU9HZg5B6k5+tJSe8oh/T?= =?us-ascii?Q?Ekt5klv60v8vDBHmmryPZQz16Ej8pUO2Xz6guhSC+x91ECJYCQS+osppNtGq?= =?us-ascii?Q?aAFpCp/zO+gln+jVoUTCHwgj+c+O5DxjQysneMrijXV+ttMcQD2JRv3Gf4gU?= =?us-ascii?Q?QRhk5WnhMocHCrrSAtS+OIiY3IRED9EzJCnUVIAeWegnJ6mMlkJQkTbESQ/b?= =?us-ascii?Q?O+LWIOiU9H215ogGTbzvj/RVhhSBSHvTOEh0Xu9a+J7Ii51cZ5z6IqAPfp6s?= =?us-ascii?Q?wcjYM2+qIFfNeY5mePqNqaM1NyPueoc4l0Y5YlJkw5qxcFGLtGV8HS9CF+yv?= =?us-ascii?Q?1+ATajSRU3P+eTEDJJNai0iEQP4n0H01majcJKq7gA9kLtaNFQQkC7j3+hdw?= =?us-ascii?Q?ZQpJIB0+1SbP8VNEiUU7aIrUUg8aQFZjxFeY4gfdG5tsduziWuUOsMu+U0CI?= =?us-ascii?Q?6v5xh0+KXSLBk6NamsS8x58Z0U33Vg5rbUE8qgERkW6zSmpbTTdLyN28jVho?= =?us-ascii?Q?M4ClD9AuJyTCy3I/Z7BGPt5jI95S27UlGLMnvIkdbvR3yufbaHJkpjmmvGYd?= =?us-ascii?Q?NgUM2CRvhkG7Ji2CBndchy9oPqCMAeg3eYsf+KrK+q0ovvlabEalJinVObig?= =?us-ascii?Q?TSSbdR0H/kfzy1gDNNpe/4AdSZOf59TJDwaWXK+jM39Nkp7gLyD03bqfcwbL?= =?us-ascii?Q?JZY/dwA9v9kG0bHAh/w5wKcdKnmq30/V82AXevnuZWQo9nT/ByHDo9w5itbe?= =?us-ascii?Q?pmllZbrBAzCl4yc9sxURxPPi1D9+1fSUPL8iCbov1T3jBQnXaXY6+xEvnZkB?= =?us-ascii?Q?CgCSE9D1mWHeSkx/srxq2oT4YwqhCEhY+FbnXh7fog7/pcEeIG0mfe3O6T2c?= =?us-ascii?Q?sK4KM869ep2N/S2sF2cEFcv7jw7zH6ZctcZ4x+ZfJXKBb2NnX77GwTCMFejY?= =?us-ascii?Q?zOV/eYtwM5ETniK9NLmwxsenUqpHrI0sjiChwNg5DYK1nSsw3L+V89eod9mp?= =?us-ascii?Q?HsmYAOdVQmZptQM0uCaEfgUwMM/iVuaXvGyAbp3TVVf8egITWGQLJ9YbDVi0?= =?us-ascii?Q?uK5HJ44lX3tazGJu2Ye9JfbKIE+1j1IexzM1u/5BDN1THkXiCQ0tc6oPWM2u?= =?us-ascii?Q?kTtL7VhsC6p5en1vuAJwkgUY9qdyFaLzUEwm8C3vncxOJUg8616265o1FVpQ?= =?us-ascii?Q?VCCxxm5EWMNBwc9XEa6HlwsS6e17LkgRlcR0BV7T5gbBltmYG+quLtni5hWu?= =?us-ascii?Q?aNNzmnZocPlolwtFMilivCCbw041Z84ipzs+HXlttfwRbnGgEv07NcVU9l4k?= =?us-ascii?Q?aCD1Q=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB2838;6:dpSL4ksR3AjCu7UgpQL6Ca7q5V9j8L6CyycCpy4MxJEJT+rOP1v6i4ytWC5u9e0TST0Qu4Tyvtg0Jx97N7naaGWC1l6iD8uuaOLC0XxPMkZv2c0HBkVXVzqfxF/bfxLp25gp0sc99iadse95GvDQysJIJuOiKeOqWKeiR9RetfIJiHcYAJ4S2mLpq6Mf1Eu7Eifw125M9VGOy6gACdVkcRDzx0GtAI+BviRVQpOImqbC+VW2xgYN5iATW3PNpBn3szC/QDL+je44BA/tkYCBYhnza2zKpVv8rHmX5kUI5cua5by6gdN72jHdprprzz+Tr3BegQBDks/S2G/Ks7grbs927pcS6yfWaBCcfYhnfounBgqVgad7uGco+oryxyplr767wYsudwI3UNPbyCBfc7DSMbgBfmH4gic5P9qL/K4=;5:7rfmJXvW5pSlKcJ5NNiZR+6rTA9+Tdzf27DjHqfvoJLP/nkeM4HbDwL6XDeTf7Evk9LDADx7Zg8Mqw4CnAEuJdB+sfLbi9PZbCYGs7sSb5xizyLihZQxQcci7Si2bLys0q2+LMahNQfcKuoUa9BNow==;24:840Rzrql5qKgYg0MzbA72ZXG+7oBcN8XHhmSYSqiQpk3sY467JInWvMsRDFJcVhoFMssKZXUrWCpRNxU9O8K53HItomtZPX7IuSOzpYp7oE= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB2838;7:O+gI/BObPDTDh7uys8nRv2nhrUK47ogzLAnGrLMfDcOpis0Bv+qa14hfEyPwyEDklag8ekzyWT4Id+G/cbLC8ifQz/+0ycHnV8a1Fw6bMBRrhVM9Zxr1K4vjtyedLBfESxciPYSFwsGqr1ccrml27UOx2Xuubsid+lZL0GaUYOxYyjCaOdafBdewmjdW20uYUF0kh7qoB1LTwBM1G0TG0bQnV8H8WEi8HZ7ZSOuPue7PVs6ZahhsUmpN8IXEjpyG9Es6uDA+PeVgGLAK1T4D2hApDio3MHaD7nzj7EDlWap2eUfXaO7BT0WuA6/zby7zRgO6E1In9icf2SdqkqhyYyI7A1mIO4z5fb7V4C7pF6yFgiHVdtUGJYUra6SbaaE0F8XN0gBYXorGo1Mx80gNjlfW4ADIxzrPWqxMobq5WJlOcFsgw5RooRvOo//fVg+58NoQEhvJq8oJ5tAx23hsOg== X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Dec 2016 08:48:39.5065 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR07MB2838 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --- 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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