Skip to content

Commit fe3ef61

Browse files
committed
Merge branch 'switchdev_offload_flags'
Roopa Prabhu says: ==================== switchdev offload flags This patch series introduces new offload flags for switchdev. Kernel network subsystems can use this flag to accelerate network functions by offloading to hw. I expect that there will be need for subsystem specific feature flag in the future. This patch series currently only addresses bridge driver link attribute offloads to hardware. Looking at the current state of bridge l2 offload in the kernel, - flag 'self' is the way to directly manage the bridge device in hw via the ndo_bridge_setlink/ndo_bridge_getlink calls - flag 'master' is always used to manage the in kernel bridge devices via the same ndo_bridge_setlink/ndo_bridge_getlink calls Today these are used separately. The nic offloads use hwmode "vepa/veb" to go directly to hw with the "self" flag. At this point i am trying not to introduce any new user facing flags/attributes. In the model where we want the kernel bridging to be accelerated with hardware, we very much want the bridge driver to be involved. In this proposal, - The offload flag/bit helps switch asic drivers to indicate that they accelerate the kernel networking objects/functions - The user does not have to specify a new flag to do so. A bridge created with switch asic ports will be accelerated if the switch driver supports it. - The user can continue to directly manage l2 in nics (ixgbe) using the existing hwmode/self flags - It also does not stop users from using the 'self' flag to talk to the switch asic driver directly - Involving the bridge driver makes sure the add/del notifications to user space go out after both kernel and hardware are programmed (To selectively offload bridge port attributes, example learning in hw only etc, we can introduce offload bits for per bridge port flag attribute as in my previous patch https://patchwork.ozlabs.org/patch/413211/. I have not included that in this series) v2 - try a different name for the offload flag/bit - tries to solve the stacked netdev case by traversing the lowerdev list to reach the switch port v3 - - Tested with bond as bridge port for the stacked device case. Includes a bond_fix_features change to not ignore the NETIF_F_HW_NETFUNC_OFFLOAD flag - Some checkpatch fixes v4 - - rename flag to NETIF_F_HW_SWITCH_OFFLOAD - add ndo_bridge_setlink/dellink handlers in bond and team drivers as suggested by jiri. - introduce default ndo_dflt_netdev_switch_port_bridge_setlink/dellink handlers that masters can use to call offload api on lowerdevs. ==================== Signed-off-by: Roopa Prabhu <[email protected]>
2 parents b2dec11 + a16a8ee commit fe3ef61

File tree

12 files changed

+206
-21
lines changed

12 files changed

+206
-21
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include <net/pkt_sched.h>
7878
#include <linux/rculist.h>
7979
#include <net/flow_keys.h>
80+
#include <net/switchdev.h>
8081
#include <net/bonding.h>
8182
#include <net/bond_3ad.h>
8283
#include <net/bond_alb.h>
@@ -979,7 +980,11 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
979980
netdev_features_t mask;
980981
struct slave *slave;
981982

982-
mask = features;
983+
/* If any slave has the offload feature flag set,
984+
* set the offload flag on the bond.
985+
*/
986+
mask = features | NETIF_F_HW_SWITCH_OFFLOAD;
987+
983988
features &= ~NETIF_F_ONE_FOR_ALL;
984989
features |= NETIF_F_ALL_FOR_ALL;
985990

@@ -3952,6 +3957,8 @@ static const struct net_device_ops bond_netdev_ops = {
39523957
.ndo_add_slave = bond_enslave,
39533958
.ndo_del_slave = bond_release,
39543959
.ndo_fix_features = bond_fix_features,
3960+
.ndo_bridge_setlink = ndo_dflt_netdev_switch_port_bridge_setlink,
3961+
.ndo_bridge_dellink = ndo_dflt_netdev_switch_port_bridge_dellink,
39553962
};
39563963

39573964
static const struct device_type bond_type = {

drivers/net/ethernet/emulex/benet/be_main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4327,7 +4327,8 @@ int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
43274327
return status;
43284328
}
43294329

4330-
static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh)
4330+
static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
4331+
u16 flags)
43314332
{
43324333
struct be_adapter *adapter = netdev_priv(dev);
43334334
struct nlattr *attr, *br_spec;

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7786,7 +7786,7 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
77867786
}
77877787

77887788
static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
7789-
struct nlmsghdr *nlh)
7789+
struct nlmsghdr *nlh, u16 flags)
77907790
{
77917791
struct ixgbe_adapter *adapter = netdev_priv(dev);
77927792
struct nlattr *attr, *br_spec;

drivers/net/ethernet/rocker/rocker.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3722,7 +3722,7 @@ static int rocker_port_fdb_dump(struct sk_buff *skb,
37223722
}
37233723

37243724
static int rocker_port_bridge_setlink(struct net_device *dev,
3725-
struct nlmsghdr *nlh)
3725+
struct nlmsghdr *nlh, u16 flags)
37263726
{
37273727
struct rocker_port *rocker_port = netdev_priv(dev);
37283728
struct nlattr *protinfo;
@@ -4030,7 +4030,8 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
40304030
NAPI_POLL_WEIGHT);
40314031
rocker_carrier_init(rocker_port);
40324032

4033-
dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
4033+
dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
4034+
NETIF_F_HW_SWITCH_OFFLOAD;
40344035

40354036
err = register_netdev(dev);
40364037
if (err) {

drivers/net/team/team.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <net/genetlink.h>
2929
#include <net/netlink.h>
3030
#include <net/sch_generic.h>
31+
#include <net/switchdev.h>
3132
#include <generated/utsrelease.h>
3233
#include <linux/if_team.h>
3334

@@ -1925,7 +1926,7 @@ static netdev_features_t team_fix_features(struct net_device *dev,
19251926
struct team *team = netdev_priv(dev);
19261927
netdev_features_t mask;
19271928

1928-
mask = features;
1929+
mask = features | NETIF_F_HW_SWITCH_OFFLOAD;
19291930
features &= ~NETIF_F_ONE_FOR_ALL;
19301931
features |= NETIF_F_ALL_FOR_ALL;
19311932

@@ -1975,6 +1976,8 @@ static const struct net_device_ops team_netdev_ops = {
19751976
.ndo_del_slave = team_del_slave,
19761977
.ndo_fix_features = team_fix_features,
19771978
.ndo_change_carrier = team_change_carrier,
1979+
.ndo_bridge_setlink = ndo_dflt_netdev_switch_port_bridge_setlink,
1980+
.ndo_bridge_dellink = ndo_dflt_netdev_switch_port_bridge_dellink,
19781981
};
19791982

19801983
/***********************

include/linux/netdev_features.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ enum {
6666
NETIF_F_HW_VLAN_STAG_FILTER_BIT,/* Receive filtering on VLAN STAGs */
6767
NETIF_F_HW_L2FW_DOFFLOAD_BIT, /* Allow L2 Forwarding in Hardware */
6868
NETIF_F_BUSY_POLL_BIT, /* Busy poll */
69+
NETIF_F_HW_SWITCH_OFFLOAD_BIT, /* HW switch offload */
6970

7071
/*
7172
* Add your fresh new feature above and remember to update
@@ -124,6 +125,7 @@ enum {
124125
#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)
125126
#define NETIF_F_HW_L2FW_DOFFLOAD __NETIF_F(HW_L2FW_DOFFLOAD)
126127
#define NETIF_F_BUSY_POLL __NETIF_F(BUSY_POLL)
128+
#define NETIF_F_HW_SWITCH_OFFLOAD __NETIF_F(HW_SWITCH_OFFLOAD)
127129

128130
/* Features valid for ethtool to change */
129131
/* = all defined minus driver/device-class-related */
@@ -159,7 +161,9 @@ enum {
159161
*/
160162
#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
161163
NETIF_F_SG | NETIF_F_HIGHDMA | \
162-
NETIF_F_FRAGLIST | NETIF_F_VLAN_CHALLENGED)
164+
NETIF_F_FRAGLIST | NETIF_F_VLAN_CHALLENGED | \
165+
NETIF_F_HW_SWITCH_OFFLOAD)
166+
163167
/*
164168
* If one device doesn't support one of these features, then disable it
165169
* for all in netdev_increment_features.

include/linux/netdevice.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,13 +1154,15 @@ struct net_device_ops {
11541154
int idx);
11551155

11561156
int (*ndo_bridge_setlink)(struct net_device *dev,
1157-
struct nlmsghdr *nlh);
1157+
struct nlmsghdr *nlh,
1158+
u16 flags);
11581159
int (*ndo_bridge_getlink)(struct sk_buff *skb,
11591160
u32 pid, u32 seq,
11601161
struct net_device *dev,
11611162
u32 filter_mask);
11621163
int (*ndo_bridge_dellink)(struct net_device *dev,
1163-
struct nlmsghdr *nlh);
1164+
struct nlmsghdr *nlh,
1165+
u16 flags);
11641166
int (*ndo_change_carrier)(struct net_device *dev,
11651167
bool new_carrier);
11661168
int (*ndo_get_phys_port_id)(struct net_device *dev,

include/net/switchdev.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,14 @@ int register_netdev_switch_notifier(struct notifier_block *nb);
4343
int unregister_netdev_switch_notifier(struct notifier_block *nb);
4444
int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
4545
struct netdev_switch_notifier_info *info);
46-
46+
int netdev_switch_port_bridge_setlink(struct net_device *dev,
47+
struct nlmsghdr *nlh, u16 flags);
48+
int netdev_switch_port_bridge_dellink(struct net_device *dev,
49+
struct nlmsghdr *nlh, u16 flags);
50+
int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev,
51+
struct nlmsghdr *nlh, u16 flags);
52+
int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev,
53+
struct nlmsghdr *nlh, u16 flags);
4754
#else
4855

4956
static inline int netdev_switch_parent_id_get(struct net_device *dev,
@@ -74,6 +81,34 @@ static inline int call_netdev_switch_notifiers(unsigned long val, struct net_dev
7481
return NOTIFY_DONE;
7582
}
7683

84+
static inline int netdev_switch_port_bridge_setlink(struct net_device *dev,
85+
struct nlmsghdr *nlh,
86+
u16 flags)
87+
{
88+
return -EOPNOTSUPP;
89+
}
90+
91+
static inline int netdev_switch_port_bridge_dellink(struct net_device *dev,
92+
struct nlmsghdr *nlh,
93+
u16 flags)
94+
{
95+
return -EOPNOTSUPP;
96+
}
97+
98+
static inline int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev,
99+
struct nlmsghdr *nlh,
100+
u16 flags)
101+
{
102+
return 0;
103+
}
104+
105+
static inline int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev,
106+
struct nlmsghdr *nlh,
107+
u16 flags)
108+
{
109+
return 0;
110+
}
111+
77112
#endif
78113

79114
#endif /* _LINUX_SWITCHDEV_H_ */

net/bridge/br_netlink.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <net/rtnetlink.h>
1717
#include <net/net_namespace.h>
1818
#include <net/sock.h>
19+
#include <net/switchdev.h>
1920
#include <uapi/linux/if_bridge.h>
2021

2122
#include "br_private.h"
@@ -494,13 +495,13 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
494495
}
495496

496497
/* Change state and parameters on port. */
497-
int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
498+
int br_setlink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags)
498499
{
499500
struct nlattr *protinfo;
500501
struct nlattr *afspec;
501502
struct net_bridge_port *p;
502503
struct nlattr *tb[IFLA_BRPORT_MAX + 1];
503-
int err = 0;
504+
int err = 0, ret_offload = 0;
504505

505506
protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
506507
afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
@@ -542,19 +543,28 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
542543
afspec, RTM_SETLINK);
543544
}
544545

546+
if (!(flags & BRIDGE_FLAGS_SELF)) {
547+
/* set bridge attributes in hardware if supported
548+
*/
549+
ret_offload = netdev_switch_port_bridge_setlink(dev, nlh,
550+
flags);
551+
if (ret_offload && ret_offload != -EOPNOTSUPP)
552+
br_warn(p->br, "error setting attrs on port %u(%s)\n",
553+
(unsigned int)p->port_no, p->dev->name);
554+
}
555+
545556
if (err == 0)
546557
br_ifinfo_notify(RTM_NEWLINK, p);
547-
548558
out:
549559
return err;
550560
}
551561

552562
/* Delete port information */
553-
int br_dellink(struct net_device *dev, struct nlmsghdr *nlh)
563+
int br_dellink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags)
554564
{
555565
struct nlattr *afspec;
556566
struct net_bridge_port *p;
557-
int err;
567+
int err = 0, ret_offload = 0;
558568

559569
afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
560570
if (!afspec)
@@ -573,6 +583,16 @@ int br_dellink(struct net_device *dev, struct nlmsghdr *nlh)
573583
*/
574584
br_ifinfo_notify(RTM_NEWLINK, p);
575585

586+
if (!(flags & BRIDGE_FLAGS_SELF)) {
587+
/* del bridge attributes in hardware
588+
*/
589+
ret_offload = netdev_switch_port_bridge_dellink(dev, nlh,
590+
flags);
591+
if (ret_offload && ret_offload != -EOPNOTSUPP)
592+
br_warn(p->br, "error deleting attrs on port %u (%s)\n",
593+
(unsigned int)p->port_no, p->dev->name);
594+
}
595+
576596
return err;
577597
}
578598
static int br_validate(struct nlattr *tb[], struct nlattr *data[])

net/bridge/br_private.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,8 @@ extern struct rtnl_link_ops br_link_ops;
819819
int br_netlink_init(void);
820820
void br_netlink_fini(void);
821821
void br_ifinfo_notify(int event, struct net_bridge_port *port);
822-
int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg);
823-
int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg);
822+
int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
823+
int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
824824
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,
825825
u32 filter_mask);
826826

0 commit comments

Comments
 (0)