Add functions and structures to allocate virtual router.
prestera_hw_vr_create() return index of allocated VR so that we can move
forward and also add another objects (e.g. router interface),
which has link to VR.
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* No changes
---
.../ethernet/marvell/prestera/prestera_hw.c | 42 +++++++++++++++++++
.../ethernet/marvell/prestera/prestera_hw.h | 4 ++
2 files changed, 46 insertions(+)
Add functions to enable routing on port, which is not in vlan.
Also we can enable routing on vlan.
prestera_hw_rif_create() take index of allocated virtual router.
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* No changes
---
.../net/ethernet/marvell/prestera/prestera.h | 23 +++++
.../ethernet/marvell/prestera/prestera_hw.c | 97 +++++++++++++++++++
.../ethernet/marvell/prestera/prestera_hw.h | 7 ++
3 files changed, 127 insertions(+)
@@ -225,6 +225,29 @@ struct prestera_event {};};+enumprestera_if_type{+/* the interface is of port type (dev,port) */+PRESTERA_IF_PORT_E=0,++/* the interface is of lag type (lag-id) */+PRESTERA_IF_LAG_E=1,++/* the interface is of Vid type (vlan-id) */+PRESTERA_IF_VID_E=3,+};++structprestera_iface{+enumprestera_if_typetype;+struct{+u32hw_dev_num;+u32port_num;+}dev_port;+u32hw_dev_num;+u16vr_id;+u16lag_id;+u16vlan_id;+};+structprestera_switchdev;structprestera_span;structprestera_rxtx;
@@ -564,8 +596,12 @@ static void prestera_hw_build_tests(void)BUILD_BUG_ON(sizeof(structprestera_msg_acl_action)!=32);BUILD_BUG_ON(sizeof(structprestera_msg_counter_req)!=16);BUILD_BUG_ON(sizeof(structprestera_msg_counter_stats)!=16);+BUILD_BUG_ON(sizeof(structprestera_msg_rif_req)!=36);BUILD_BUG_ON(sizeof(structprestera_msg_vr_req)!=8);+/* structure that are part of req/resp fw messages */+BUILD_BUG_ON(sizeof(structprestera_msg_iface)!=16);+/* check responses */BUILD_BUG_ON(sizeof(structprestera_msg_common_resp)!=8);BUILD_BUG_ON(sizeof(structprestera_msg_switch_init_resp)!=24);
@@ -0,0 +1,28 @@+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+/* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved */++#include<linux/kernel.h>+#include<linux/types.h>++#include"prestera.h"++intprestera_router_init(structprestera_switch*sw)+{+structprestera_router*router;++router=kzalloc(sizeof(*sw->router),GFP_KERNEL);+if(!router)+return-ENOMEM;++sw->router=router;+router->sw=sw;++return0;+}++voidprestera_router_fini(structprestera_switch*sw)+{+kfree(sw->router);+sw->router=NULL;+}+
Add prestera_router_hw.c. This file contains functions, which track HW
objects relations and links. This include implicity creation of objects,
that needed by requested one and implicity removing of objects, which
reference counter is became zero.
We need this layer, because kernel callbacks not always mapped to
creation of single HW object. So let it be two different layers - one
for subscribing and parsing kernel structures, and another
(prestera_router_hw.c) for HW objects relations tracking.
There is two types of objects on router_hw layer:
- Explicit objects (rif_entry) : created by higher layer.
- Implicit objects (vr) : created on demand by explicit objects.
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* No changes
---
.../net/ethernet/marvell/prestera/Makefile | 2 +-
.../marvell/prestera/prestera_router.c | 10 +
.../marvell/prestera/prestera_router_hw.c | 209 ++++++++++++++++++
.../marvell/prestera/prestera_router_hw.h | 36 +++
4 files changed, 256 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_router_hw.c
create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_router_hw.h
@@ -0,0 +1,209 @@+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+/* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved */++#include<linux/rhashtable.h>++#include"prestera.h"+#include"prestera_hw.h"+#include"prestera_router_hw.h"+#include"prestera_acl.h"++/* +--++*+------->|vr|+*|+--++*|+*+-+-------++*|rif_entry|+*+---------++*Rifis+*usedas+*entrypoint+*forvrinhw+*/++intprestera_router_hw_init(structprestera_switch*sw)+{+INIT_LIST_HEAD(&sw->router->vr_list);+INIT_LIST_HEAD(&sw->router->rif_entry_list);++return0;+}++staticstructprestera_vr*__prestera_vr_find(structprestera_switch*sw,+u32tb_id)+{+structprestera_vr*vr;++list_for_each_entry(vr,&sw->router->vr_list,router_node){+if(vr->tb_id==tb_id)+returnvr;+}++returnNULL;+}++staticstructprestera_vr*__prestera_vr_create(structprestera_switch*sw,+u32tb_id,+structnetlink_ext_ack*extack)+{+structprestera_vr*vr;+u16hw_vr_id;+interr;++err=prestera_hw_vr_create(sw,&hw_vr_id);+if(err)+returnERR_PTR(-ENOMEM);++vr=kzalloc(sizeof(*vr),GFP_KERNEL);+if(!vr){+err=-ENOMEM;+gotoerr_alloc_vr;+}++vr->tb_id=tb_id;+vr->hw_vr_id=hw_vr_id;++list_add(&vr->router_node,&sw->router->vr_list);++returnvr;++err_alloc_vr:+prestera_hw_vr_delete(sw,hw_vr_id);+kfree(vr);+returnERR_PTR(err);+}++staticvoid__prestera_vr_destroy(structprestera_switch*sw,+structprestera_vr*vr)+{+prestera_hw_vr_delete(sw,vr->hw_vr_id);+list_del(&vr->router_node);+kfree(vr);+}++staticstructprestera_vr*prestera_vr_get(structprestera_switch*sw,u32tb_id,+structnetlink_ext_ack*extack)+{+structprestera_vr*vr;++vr=__prestera_vr_find(sw,tb_id);+if(!vr)+vr=__prestera_vr_create(sw,tb_id,extack);+if(IS_ERR(vr))+returnERR_CAST(vr);++returnvr;+}++staticvoidprestera_vr_put(structprestera_switch*sw,structprestera_vr*vr)+{+if(!vr->ref_cnt)+__prestera_vr_destroy(sw,vr);+}++/* iface is overhead struct. vr_id also can be removed. */+staticint+__prestera_rif_entry_key_copy(conststructprestera_rif_entry_key*in,+structprestera_rif_entry_key*out)+{+memset(out,0,sizeof(*out));++switch(in->iface.type){+casePRESTERA_IF_PORT_E:+out->iface.dev_port.hw_dev_num=in->iface.dev_port.hw_dev_num;+out->iface.dev_port.port_num=in->iface.dev_port.port_num;+break;+casePRESTERA_IF_LAG_E:+out->iface.lag_id=in->iface.lag_id;+break;+casePRESTERA_IF_VID_E:+out->iface.vlan_id=in->iface.vlan_id;+break;+default:+pr_err("Unsupported iface type");+return-EINVAL;+}++out->iface.type=in->iface.type;+return0;+}++structprestera_rif_entry*+prestera_rif_entry_find(conststructprestera_switch*sw,+conststructprestera_rif_entry_key*k)+{+structprestera_rif_entry*rif_entry;+structprestera_rif_entry_keylk;/* lookup key */++if(__prestera_rif_entry_key_copy(k,&lk))+returnNULL;++list_for_each_entry(rif_entry,&sw->router->rif_entry_list,+router_node){+if(!memcmp(k,&rif_entry->key,sizeof(*k)))+returnrif_entry;+}++returnNULL;+}++voidprestera_rif_entry_destroy(structprestera_switch*sw,+structprestera_rif_entry*e)+{+structprestera_ifaceiface;++list_del(&e->router_node);++memcpy(&iface,&e->key.iface,sizeof(iface));+iface.vr_id=e->vr->hw_vr_id;+prestera_hw_rif_delete(sw,e->hw_id,&iface);++e->vr->ref_cnt--;+prestera_vr_put(sw,e->vr);+kfree(e);+}++structprestera_rif_entry*+prestera_rif_entry_create(structprestera_switch*sw,+structprestera_rif_entry_key*k,+u32tb_id,constunsignedchar*addr)+{+interr;+structprestera_rif_entry*e;+structprestera_ifaceiface;++e=kzalloc(sizeof(*e),GFP_KERNEL);+if(!e)+gotoerr_kzalloc;++if(__prestera_rif_entry_key_copy(k,&e->key))+gotoerr_key_copy;++e->vr=prestera_vr_get(sw,tb_id,NULL);+if(IS_ERR(e->vr))+gotoerr_vr_get;++e->vr->ref_cnt++;+memcpy(&e->addr,addr,sizeof(e->addr));++/* HW */+memcpy(&iface,&e->key.iface,sizeof(iface));+iface.vr_id=e->vr->hw_vr_id;+err=prestera_hw_rif_create(sw,&iface,e->addr,&e->hw_id);+if(err)+gotoerr_hw_create;++list_add(&e->router_node,&sw->router->rif_entry_list);++returne;++err_hw_create:+e->vr->ref_cnt--;+prestera_vr_put(sw,e->vr);+err_vr_get:+err_key_copy:+kfree(e);+err_kzalloc:+returnNULL;+}+
Initial implementation of notification handlers. For now this is just
stub.
So that we can move forward and add prestera_router_hw's objects
manipulations.
We support several addresses on interface. We just have nothing to do for
second address, because rif is already enabled on this interface, after
first one.
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* Update commit message: explanation about addresses on rif
---
.../net/ethernet/marvell/prestera/prestera.h | 4 +
.../ethernet/marvell/prestera/prestera_main.c | 2 +-
.../marvell/prestera/prestera_router.c | 105 ++++++++++++++++++
3 files changed, 110 insertions(+), 1 deletion(-)
@@ -3,10 +3,98 @@#include<linux/kernel.h>#include<linux/types.h>+#include<linux/inetdevice.h>#include"prestera.h"#include"prestera_router_hw.h"+staticint__prestera_inetaddr_port_event(structnet_device*port_dev,+unsignedlongevent,+structnetlink_ext_ack*extack)+{+structprestera_port*port=netdev_priv(port_dev);+interr;++err=prestera_is_valid_mac_addr(port,port_dev->dev_addr);+if(err){+NL_SET_ERR_MSG_MOD(extack,"RIF MAC must have the same prefix");+returnerr;+}++switch(event){+caseNETDEV_UP:+caseNETDEV_DOWN:+break;+}++return0;+}++staticint__prestera_inetaddr_event(structprestera_switch*sw,+structnet_device*dev,+unsignedlongevent,+structnetlink_ext_ack*extack)+{+if(prestera_netdev_check(dev)&&!netif_is_bridge_port(dev)&&+!netif_is_lag_port(dev)&&!netif_is_ovs_port(dev))+return__prestera_inetaddr_port_event(dev,event,extack);++return0;+}++staticint__prestera_inetaddr_cb(structnotifier_block*nb,+unsignedlongevent,void*ptr)+{+structin_ifaddr*ifa=(structin_ifaddr*)ptr;+structnet_device*dev=ifa->ifa_dev->dev;+structprestera_router*router=container_of(nb,+structprestera_router,+inetaddr_nb);+structin_device*idev;+interr=0;++if(event!=NETDEV_DOWN)+gotoout;++/* Ignore if this is not latest address */+idev=__in_dev_get_rtnl(dev);+if(idev&&idev->ifa_list)+gotoout;++err=__prestera_inetaddr_event(router->sw,dev,event,NULL);+out:+returnnotifier_from_errno(err);+}++staticint__prestera_inetaddr_valid_cb(structnotifier_block*nb,+unsignedlongevent,void*ptr)+{+structin_validator_info*ivi=(structin_validator_info*)ptr;+structnet_device*dev=ivi->ivi_dev->dev;+structprestera_router*router=container_of(nb,+structprestera_router,+inetaddr_valid_nb);+structin_device*idev;+interr=0;++if(event!=NETDEV_UP)+gotoout;++/* Ignore if this is not first address */+idev=__in_dev_get_rtnl(dev);+if(idev&&idev->ifa_list)+gotoout;++if(ipv4_is_multicast(ivi->ivi_addr)){+err=-EINVAL;+gotoout;+}++err=__prestera_inetaddr_event(router->sw,dev,event,ivi->extack);+out:+returnnotifier_from_errno(err);+}+intprestera_router_init(structprestera_switch*sw){structprestera_router*router;
@@ -23,8 +111,22 @@ int prestera_router_init(struct prestera_switch *sw)if(err)gotoerr_router_lib_init;+router->inetaddr_valid_nb.notifier_call=__prestera_inetaddr_valid_cb;+err=register_inetaddr_validator_notifier(&router->inetaddr_valid_nb);+if(err)+gotoerr_register_inetaddr_validator_notifier;++router->inetaddr_nb.notifier_call=__prestera_inetaddr_cb;+err=register_inetaddr_notifier(&router->inetaddr_nb);+if(err)+gotoerr_register_inetaddr_notifier;+return0;+err_register_inetaddr_notifier:+unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);+err_register_inetaddr_validator_notifier:+/* prestera_router_hw_fini */err_router_lib_init:kfree(sw->router);returnerr;
@@ -32,6 +134,9 @@ int prestera_router_init(struct prestera_switch *sw)voidprestera_router_fini(structprestera_switch*sw){+unregister_inetaddr_notifier(&sw->router->inetaddr_nb);+unregister_inetaddr_validator_notifier(&sw->router->inetaddr_valid_nb);+/* router_hw_fini */kfree(sw->router);sw->router=NULL;}
Add inetaddr notifiers to support add/del IPv4 address on switchdev
port. We create TRAP on first address, added on port and delete TRAP,
when last address removed.
Currently, driver supports only regular port to became routed.
Other port type support will be added later
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* Remove useless assigment in prestera_fix_tb_id
---
.../marvell/prestera/prestera_router.c | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
@@ -4,16 +4,31 @@#include<linux/kernel.h>#include<linux/types.h>#include<linux/inetdevice.h>+#include<net/switchdev.h>#include"prestera.h"#include"prestera_router_hw.h"+/* This util to be used, to convert kernel rules for default vr in hw_vr */+staticu32prestera_fix_tb_id(u32tb_id)+{+if(tb_id==RT_TABLE_UNSPEC||+tb_id==RT_TABLE_LOCAL||+tb_id==RT_TABLE_DEFAULT)+tb_id=RT_TABLE_MAIN;++returntb_id;+}+staticint__prestera_inetaddr_port_event(structnet_device*port_dev,unsignedlongevent,structnetlink_ext_ack*extack){structprestera_port*port=netdev_priv(port_dev);interr;+structprestera_rif_entry*re;+structprestera_rif_entry_keyre_key={};+u32kern_tb_id;err=prestera_is_valid_mac_addr(port,port_dev->dev_addr);if(err){
@@ -21,9 +36,34 @@ static int __prestera_inetaddr_port_event(struct net_device *port_dev,returnerr;}+kern_tb_id=l3mdev_fib_table(port_dev);+re_key.iface.type=PRESTERA_IF_PORT_E;+re_key.iface.dev_port.hw_dev_num=port->dev_id;+re_key.iface.dev_port.port_num=port->hw_id;+re=prestera_rif_entry_find(port->sw,&re_key);+switch(event){caseNETDEV_UP:+if(re){+NL_SET_ERR_MSG_MOD(extack,"rif_entry already exist");+return-EEXIST;+}+re=prestera_rif_entry_create(port->sw,&re_key,+prestera_fix_tb_id(kern_tb_id),+port_dev->dev_addr);+if(!re){+NL_SET_ERR_MSG_MOD(extack,"Can't create rif_entry");+return-EINVAL;+}+dev_hold(port_dev);+break;caseNETDEV_DOWN:+if(!re){+NL_SET_ERR_MSG_MOD(extack,"rif_entry not exist");+return-EEXIST;+}+prestera_rif_entry_destroy(port->sw,re);+dev_put(port_dev);break;}
@@ -225,6 +225,29 @@ struct prestera_event {};};+enumprestera_if_type{+/* the interface is of port type (dev,port) */+PRESTERA_IF_PORT_E=0,++/* the interface is of lag type (lag-id) */+PRESTERA_IF_LAG_E=1,++/* the interface is of Vid type (vlan-id) */+PRESTERA_IF_VID_E=3,+};++structprestera_iface{+enumprestera_if_typetype;+struct{+u32hw_dev_num;+u32port_num;+}dev_port;+u32hw_dev_num;+u16vr_id;+u16lag_id;+u16vlan_id;+};+structprestera_switchdev;structprestera_span;structprestera_rxtx;
@@ -564,8 +596,12 @@ static void prestera_hw_build_tests(void)BUILD_BUG_ON(sizeof(structprestera_msg_acl_action)!=32);BUILD_BUG_ON(sizeof(structprestera_msg_counter_req)!=16);BUILD_BUG_ON(sizeof(structprestera_msg_counter_stats)!=16);+BUILD_BUG_ON(sizeof(structprestera_msg_rif_req)!=36);BUILD_BUG_ON(sizeof(structprestera_msg_vr_req)!=8);+/* structure that are part of req/resp fw messages */+BUILD_BUG_ON(sizeof(structprestera_msg_iface)!=16);+/* check responses */BUILD_BUG_ON(sizeof(structprestera_msg_common_resp)!=8);BUILD_BUG_ON(sizeof(structprestera_msg_switch_init_resp)!=24);
@@ -1769,6 +1806,66 @@ int prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)&req.cmd,sizeof(req));}+staticintprestera_iface_to_msg(structprestera_iface*iface,+structprestera_msg_iface*msg_if)+{+switch(iface->type){+casePRESTERA_IF_PORT_E:+casePRESTERA_IF_VID_E:+msg_if->port=__cpu_to_le32(iface->dev_port.port_num);+msg_if->dev=__cpu_to_le32(iface->dev_port.hw_dev_num);+break;+casePRESTERA_IF_LAG_E:+msg_if->lag_id=__cpu_to_le16(iface->lag_id);+break;+default:+return-EOPNOTSUPP;+}++msg_if->vr_id=__cpu_to_le16(iface->vr_id);+msg_if->vid=__cpu_to_le16(iface->vlan_id);+msg_if->type=iface->type;+return0;+}++intprestera_hw_rif_create(structprestera_switch*sw,+structprestera_iface*iif,u8*mac,u16*rif_id)+{+structprestera_msg_rif_reqreq;+structprestera_msg_rif_respresp;+interr;
Same comment as before
+
+ memcpy(req.mac, mac, ETH_ALEN);
Each RIF can use whatever MAC it wants? You don't have limitations on
common prefix or something like that? Guess it depends on how many RIFs
you can support
@@ -0,0 +1,28 @@+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+/* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved */++#include<linux/kernel.h>+#include<linux/types.h>++#include"prestera.h"++intprestera_router_init(structprestera_switch*sw)+{+structprestera_router*router;++router=kzalloc(sizeof(*sw->router),GFP_KERNEL);+if(!router)+return-ENOMEM;++sw->router=router;+router->sw=sw;++return0;+}++voidprestera_router_fini(structprestera_switch*sw)+{+kfree(sw->router);+sw->router=NULL;+}+
On Mon, Dec 27, 2021 at 11:52:29PM +0200, Yevhen Orlov wrote:
quoted hunk
Add prestera_router_hw.c. This file contains functions, which track HW
objects relations and links. This include implicity creation of objects,
that needed by requested one and implicity removing of objects, which
reference counter is became zero.
We need this layer, because kernel callbacks not always mapped to
creation of single HW object. So let it be two different layers - one
for subscribing and parsing kernel structures, and another
(prestera_router_hw.c) for HW objects relations tracking.
There is two types of objects on router_hw layer:
- Explicit objects (rif_entry) : created by higher layer.
- Implicit objects (vr) : created on demand by explicit objects.
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* No changes
---
.../net/ethernet/marvell/prestera/Makefile | 2 +-
.../marvell/prestera/prestera_router.c | 10 +
.../marvell/prestera/prestera_router_hw.c | 209 ++++++++++++++++++
.../marvell/prestera/prestera_router_hw.h | 36 +++
4 files changed, 256 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_router_hw.c
create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_router_hw.h
@@ -17,7 +19,15 @@ int prestera_router_init(struct prestera_switch *sw)sw->router=router;router->sw=sw;+err=prestera_router_hw_init(sw);+if(err)+gotoerr_router_lib_init;+return0;++err_router_lib_init:+kfree(sw->router);+returnerr;}voidprestera_router_fini(structprestera_switch*sw)
Looks suspicious that you don't call prestera_router_hw_fini() here. You
can at least verify that the two lists you initialize in
prestera_router_hw_init() are indeed empty.
@@ -0,0 +1,209 @@+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+/* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved */++#include<linux/rhashtable.h>++#include"prestera.h"+#include"prestera_hw.h"+#include"prestera_router_hw.h"+#include"prestera_acl.h"++/* +--++*+------->|vr|+*|+--++*|+*+-+-------++*|rif_entry|+*+---------++*Rifis+*usedas+*entrypoint+*forvrinhw+*/++intprestera_router_hw_init(structprestera_switch*sw)+{+INIT_LIST_HEAD(&sw->router->vr_list);+INIT_LIST_HEAD(&sw->router->rif_entry_list);++return0;+}++staticstructprestera_vr*__prestera_vr_find(structprestera_switch*sw,+u32tb_id)+{+structprestera_vr*vr;++list_for_each_entry(vr,&sw->router->vr_list,router_node){
Probably better to store VRs in something like IDR instead of a linked
list
It's easier to maintain/review code that follows a pattern of create()
followed by destroy(). You can see if the error path is the same as what
you have in destroy()
On Mon, Dec 27, 2021 at 11:52:30PM +0200, Yevhen Orlov wrote:
quoted hunk
Initial implementation of notification handlers. For now this is just
stub.
So that we can move forward and add prestera_router_hw's objects
manipulations.
We support several addresses on interface. We just have nothing to do for
second address, because rif is already enabled on this interface, after
first one.
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* Update commit message: explanation about addresses on rif
---
.../net/ethernet/marvell/prestera/prestera.h | 4 +
.../ethernet/marvell/prestera/prestera_main.c | 2 +-
.../marvell/prestera/prestera_router.c | 105 ++++++++++++++++++
3 files changed, 110 insertions(+), 1 deletion(-)
@@ -3,10 +3,98 @@#include<linux/kernel.h>#include<linux/types.h>+#include<linux/inetdevice.h>#include"prestera.h"#include"prestera_router_hw.h"+staticint__prestera_inetaddr_port_event(structnet_device*port_dev,+unsignedlongevent,+structnetlink_ext_ack*extack)+{+structprestera_port*port=netdev_priv(port_dev);+interr;++err=prestera_is_valid_mac_addr(port,port_dev->dev_addr);+if(err){+NL_SET_ERR_MSG_MOD(extack,"RIF MAC must have the same prefix");+returnerr;+}++switch(event){+caseNETDEV_UP:+caseNETDEV_DOWN:+break;+}
If you are only implementing these in the next patch, then add these
then
quoted hunk
++ return 0;+}++static int __prestera_inetaddr_event(struct prestera_switch *sw,+ struct net_device *dev,+ unsigned long event,+ struct netlink_ext_ack *extack)+{+ if (prestera_netdev_check(dev) && !netif_is_bridge_port(dev) &&+ !netif_is_lag_port(dev) && !netif_is_ovs_port(dev))
Your netdev notifier doesn't allow linking to an OVS bridge, so I'm not
sure what is the purpose of this check
Also, better use early return
What happens to that RIF when the port is linked to a bridge or unlinked
from one?
quoted hunk
+ return __prestera_inetaddr_port_event(dev, event, extack);++ return 0;+}++static int __prestera_inetaddr_cb(struct notifier_block *nb,+ unsigned long event, void *ptr)+{+ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;+ struct net_device *dev = ifa->ifa_dev->dev;+ struct prestera_router *router = container_of(nb,+ struct prestera_router,+ inetaddr_nb);+ struct in_device *idev;+ int err = 0;++ if (event != NETDEV_DOWN)+ goto out;++ /* Ignore if this is not latest address */+ idev = __in_dev_get_rtnl(dev);+ if (idev && idev->ifa_list)+ goto out;++ err = __prestera_inetaddr_event(router->sw, dev, event, NULL);+out:+ return notifier_from_errno(err);+}++static int __prestera_inetaddr_valid_cb(struct notifier_block *nb,+ unsigned long event, void *ptr)+{+ struct in_validator_info *ivi = (struct in_validator_info *)ptr;+ struct net_device *dev = ivi->ivi_dev->dev;+ struct prestera_router *router = container_of(nb,+ struct prestera_router,+ inetaddr_valid_nb);+ struct in_device *idev;+ int err = 0;++ if (event != NETDEV_UP)+ goto out;++ /* Ignore if this is not first address */+ idev = __in_dev_get_rtnl(dev);+ if (idev && idev->ifa_list)+ goto out;++ if (ipv4_is_multicast(ivi->ivi_addr)) {+ err = -EINVAL;
On Mon, Dec 27, 2021 at 11:52:31PM +0200, Yevhen Orlov wrote:
quoted hunk
Add inetaddr notifiers to support add/del IPv4 address on switchdev
port. We create TRAP on first address, added on port and delete TRAP,
when last address removed.
Currently, driver supports only regular port to became routed.
Other port type support will be added later
Co-developed-by: Taras Chornyi <redacted>
Signed-off-by: Taras Chornyi <redacted>
Co-developed-by: Oleksandr Mazur <redacted>
Signed-off-by: Oleksandr Mazur <redacted>
Signed-off-by: Yevhen Orlov <redacted>
---
v1-->v2
* Remove useless assigment in prestera_fix_tb_id
---
.../marvell/prestera/prestera_router.c | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
@@ -4,16 +4,31 @@#include<linux/kernel.h>#include<linux/types.h>#include<linux/inetdevice.h>+#include<net/switchdev.h>#include"prestera.h"#include"prestera_router_hw.h"+/* This util to be used, to convert kernel rules for default vr in hw_vr */+staticu32prestera_fix_tb_id(u32tb_id)+{+if(tb_id==RT_TABLE_UNSPEC||+tb_id==RT_TABLE_LOCAL||+tb_id==RT_TABLE_DEFAULT)+tb_id=RT_TABLE_MAIN;++returntb_id;+}+staticint__prestera_inetaddr_port_event(structnet_device*port_dev,unsignedlongevent,structnetlink_ext_ack*extack){structprestera_port*port=netdev_priv(port_dev);interr;+structprestera_rif_entry*re;+structprestera_rif_entry_keyre_key={};+u32kern_tb_id;
Reverse xmas tree
quoted hunk
err = prestera_is_valid_mac_addr(port, port_dev->dev_addr);
if (err) {
@@ -21,9 +36,34 @@ static int __prestera_inetaddr_port_event(struct net_device *port_dev, return err; }+ kern_tb_id = l3mdev_fib_table(port_dev);+ re_key.iface.type = PRESTERA_IF_PORT_E;+ re_key.iface.dev_port.hw_dev_num = port->dev_id;+ re_key.iface.dev_port.port_num = port->hw_id;+ re = prestera_rif_entry_find(port->sw, &re_key);+ switch (event) { case NETDEV_UP:+ if (re) {+ NL_SET_ERR_MSG_MOD(extack, "rif_entry already exist");
These messages are communicated to user space so use a message that is
more user friendly / informative
On Thu, Dec 30, 2021 at 03:44:50PM +0200, Ido Schimmel wrote:
On Mon, Dec 27, 2021 at 11:52:27PM +0200, Yevhen Orlov wrote:
quoted
Add functions to enable routing on port, which is not in vlan.
Also we can enable routing on vlan.
I don't understand these two lines. Can you explain for which netdev
types you can create a router interface?
Sure.
For now we support only regular port (has no upper or lower dev).
But ABI potentially support RIF on bridge/vlan (see prestera_if_type).
This feature will be implemented soon.