Skip to content

Commit 090096b

Browse files
Vlad Yasevichdavem330
authored andcommitted
net: generic fdb support for drivers without ndo_fdb_<op>
If the driver does not support the ndo_op use the generic handler for it. This should work in the majority of cases. Eventually the fdb_dflt_add call gets translated into a __dev_set_rx_mode() call which should handle hardware support for filtering via the IFF_UNICAST_FLT flag. Namely IFF_UNICAST_FLT indicates if the hardware can do unicast address filtering. If no support is available the device is put into promisc mode. Signed-off-by: Vlad Yasevich <[email protected]> Signed-off-by: John Fastabend <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6906f4e commit 090096b

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

include/linux/rtnetlink.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
6969
struct netlink_callback *cb,
7070
struct net_device *dev,
7171
int idx);
72+
extern int ndo_dflt_fdb_add(struct ndmsg *ndm,
73+
struct nlattr *tb[],
74+
struct net_device *dev,
75+
const unsigned char *addr,
76+
u16 flags);
77+
extern int ndo_dflt_fdb_del(struct ndmsg *ndm,
78+
struct nlattr *tb[],
79+
struct net_device *dev,
80+
const unsigned char *addr);
7281

7382
extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
7483
struct net_device *dev, u16 mode);

net/core/rtnetlink.c

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,38 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type)
20482048
rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
20492049
}
20502050

2051+
/**
2052+
* ndo_dflt_fdb_add - default netdevice operation to add an FDB entry
2053+
*/
2054+
int ndo_dflt_fdb_add(struct ndmsg *ndm,
2055+
struct nlattr *tb[],
2056+
struct net_device *dev,
2057+
const unsigned char *addr,
2058+
u16 flags)
2059+
{
2060+
int err = -EINVAL;
2061+
2062+
/* If aging addresses are supported device will need to
2063+
* implement its own handler for this.
2064+
*/
2065+
if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
2066+
pr_info("%s: FDB only supports static addresses\n", dev->name);
2067+
return err;
2068+
}
2069+
2070+
if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
2071+
err = dev_uc_add_excl(dev, addr);
2072+
else if (is_multicast_ether_addr(addr))
2073+
err = dev_mc_add_excl(dev, addr);
2074+
2075+
/* Only return duplicate errors if NLM_F_EXCL is set */
2076+
if (err == -EEXIST && !(flags & NLM_F_EXCL))
2077+
err = 0;
2078+
2079+
return err;
2080+
}
2081+
EXPORT_SYMBOL(ndo_dflt_fdb_add);
2082+
20512083
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
20522084
{
20532085
struct net *net = sock_net(skb->sk);
@@ -2100,10 +2132,13 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
21002132
}
21012133

21022134
/* Embedded bridge, macvlan, and any other device support */
2103-
if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_add) {
2104-
err = dev->netdev_ops->ndo_fdb_add(ndm, tb,
2105-
dev, addr,
2106-
nlh->nlmsg_flags);
2135+
if ((ndm->ndm_flags & NTF_SELF)) {
2136+
if (dev->netdev_ops->ndo_fdb_add)
2137+
err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr,
2138+
nlh->nlmsg_flags);
2139+
else
2140+
err = ndo_dflt_fdb_add(ndm, tb, dev, addr,
2141+
nlh->nlmsg_flags);
21072142

21082143
if (!err) {
21092144
rtnl_fdb_notify(dev, addr, RTM_NEWNEIGH);
@@ -2114,6 +2149,35 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
21142149
return err;
21152150
}
21162151

2152+
/**
2153+
* ndo_dflt_fdb_del - default netdevice operation to delete an FDB entry
2154+
*/
2155+
int ndo_dflt_fdb_del(struct ndmsg *ndm,
2156+
struct nlattr *tb[],
2157+
struct net_device *dev,
2158+
const unsigned char *addr)
2159+
{
2160+
int err = -EOPNOTSUPP;
2161+
2162+
/* If aging addresses are supported device will need to
2163+
* implement its own handler for this.
2164+
*/
2165+
if (ndm->ndm_state & NUD_PERMANENT) {
2166+
pr_info("%s: FDB only supports static addresses\n", dev->name);
2167+
return -EINVAL;
2168+
}
2169+
2170+
if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
2171+
err = dev_uc_del(dev, addr);
2172+
else if (is_multicast_ether_addr(addr))
2173+
err = dev_mc_del(dev, addr);
2174+
else
2175+
err = -EINVAL;
2176+
2177+
return err;
2178+
}
2179+
EXPORT_SYMBOL(ndo_dflt_fdb_del);
2180+
21172181
static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
21182182
{
21192183
struct net *net = sock_net(skb->sk);
@@ -2171,8 +2235,11 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
21712235
}
21722236

21732237
/* Embedded bridge, macvlan, and any other device support */
2174-
if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
2175-
err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr);
2238+
if (ndm->ndm_flags & NTF_SELF) {
2239+
if (dev->netdev_ops->ndo_fdb_del)
2240+
err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr);
2241+
else
2242+
err = ndo_dflt_fdb_del(ndm, tb, dev, addr);
21762243

21772244
if (!err) {
21782245
rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
@@ -2257,6 +2324,8 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
22572324

22582325
if (dev->netdev_ops->ndo_fdb_dump)
22592326
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
2327+
else
2328+
ndo_dflt_fdb_dump(skb, cb, dev, idx);
22602329
}
22612330
rcu_read_unlock();
22622331

0 commit comments

Comments
 (0)