diff options
| author | David S. Miller <davem@davemloft.net> | 2017-09-27 21:33:28 +0300 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-09-27 21:33:28 +0300 |
| commit | a2e4a21906e1ff7d2db9ce2e446e76abc905b79f (patch) | |
| tree | c3a44a2af57194c8b5a5847bd880e27d1e285c2e /include | |
| parent | 1ca94d7936a409ff263b6e0225fefea8956f4291 (diff) | |
| parent | 664375e9567b5eeece8d9ebf85eaf5107cab382d (diff) | |
| download | linux-a2e4a21906e1ff7d2db9ce2e446e76abc905b79f.tar.xz | |
Merge branch 'mlxsw-Add-support-for-offloading-IPv4-multicast-routes'
Jiri Pirko says:
====================
mlxsw: Add support for offloading IPv4 multicast routes
Yotam says:
This patch-set introduces offloading of the kernel IPv4 multicast router
logic in the Spectrum driver.
The first patch makes the Spectrum driver ignore FIB notifications that are
not of address family IPv4 or IPv6. This is needed in order to prevent
crashes while the next patches introduce the RTNL_FAMILY_IPMR FIB
notifications.
Patches 2-5 update ipmr to use the FIB notification chain for both MFC and
VIF notifications, and patches 8-12 update the Spectrum driver to register
to these notifications and offload the routes.
Similarly to IPv4 and IPv6, any failure will trigger the abort mechanism
which is updated in this patch-set to eject multicast route tables too.
At this stage, the following limitations apply:
- A multicast MFC route will be offloaded by the driver if all the output
interfaces are Spectrum router interfaces (RIFs). In any other case
(which includes pimreg device, tunnel devices and management ports) the
route will be trapped to the CPU and the packets will be forwarded by
software.
- ipmr proxy routes are not supported and will trigger the abort
mechanism.
- The MFC TTL values are currently treated as boolean: if the value is
different than 255, the traffic is forwarded to the interface and if the
value is 255 it is not forwarded. Dropping packets based on their TTL isn't
currently supported.
To allow users to have visibility on which of the routes are offloaded and
which are not, patch 6 introduces a per-route offload indication similar to
IPv4 and IPv6 routes which is sent to the user via the RTNetlink interface.
The Spectrum driver multicast router offloading support, which is
introduced in patches 8 and 9, is divided into two parts:
- The hardware logic which abstracts the Spectrum hardware and provides a
simple API for the upper levels.
- The offloading logic which gets the MFC and VIF notifications from the
kernel and updates the hardware using the hardware logic part.
Finally, the last patch makes the Spectrum router logic not ignore the
multicast FIB notifications and call the corresponding functions in the
multicast router offloading logic.
---
v2->v3:
- Move the ipmr_rule_default function definition to be inside the already
existing CONFIG_IP_MROUTE_MULTIPLE_TABLES ifdef block (patch 6)
- Remove double =0 initialization in spectrum_mr.c (patch 7)
- Fix route4 allocation size (patch 7)
v1->v2:
- Add comments for struct fields in mroute.h
- Take the mrt_lock while dumping VIFs in the fib_notifier dump callback
- Update the MFC lastuse field too
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/mroute.h | 45 | ||||
| -rw-r--r-- | include/net/fib_notifier.h | 2 | ||||
| -rw-r--r-- | include/net/netns/ipv4.h | 3 |
3 files changed, 50 insertions, 0 deletions
diff --git a/include/linux/mroute.h b/include/linux/mroute.h index d7f63339ef0b..b072a84fbe1c 100644 --- a/include/linux/mroute.h +++ b/include/linux/mroute.h @@ -5,6 +5,8 @@ #include <linux/pim.h> #include <linux/rhashtable.h> #include <net/sock.h> +#include <net/fib_rules.h> +#include <net/fib_notifier.h> #include <uapi/linux/mroute.h> #ifdef CONFIG_IP_MROUTE @@ -18,6 +20,7 @@ int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *); int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg); int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); int ip_mr_init(void); +bool ipmr_rule_default(const struct fib_rule *rule); #else static inline int ip_mroute_setsockopt(struct sock *sock, int optname, char __user *optval, unsigned int optlen) @@ -45,6 +48,11 @@ static inline int ip_mroute_opt(int opt) { return 0; } + +static inline bool ipmr_rule_default(const struct fib_rule *rule) +{ + return true; +} #endif struct vif_device { @@ -58,6 +66,14 @@ struct vif_device { int link; /* Physical interface index */ }; +struct vif_entry_notifier_info { + struct fib_notifier_info info; + struct net_device *dev; + vifi_t vif_index; + unsigned short vif_flags; + u32 tb_id; +}; + #define VIFF_STATIC 0x8000 #define VIF_EXISTS(_mrt, _idx) ((_mrt)->vif_table[_idx].dev != NULL) @@ -81,9 +97,11 @@ struct mr_table { /* mfc_flags: * MFC_STATIC - the entry was added statically (not by a routing daemon) + * MFC_OFFLOAD - the entry was offloaded to the hardware */ enum { MFC_STATIC = BIT(0), + MFC_OFFLOAD = BIT(1), }; struct mfc_cache_cmp_arg { @@ -109,6 +127,7 @@ struct mfc_cache_cmp_arg { * @wrong_if: number of wrong source interface hits * @lastuse: time of last use of the group (traffic or update) * @ttls: OIF TTL threshold array + * @refcount: reference count for this entry * @list: global entry list * @rcu: used for entry destruction */ @@ -138,14 +157,40 @@ struct mfc_cache { unsigned long wrong_if; unsigned long lastuse; unsigned char ttls[MAXVIFS]; + refcount_t refcount; } res; } mfc_un; struct list_head list; struct rcu_head rcu; }; +struct mfc_entry_notifier_info { + struct fib_notifier_info info; + struct mfc_cache *mfc; + u32 tb_id; +}; + struct rtmsg; int ipmr_get_route(struct net *net, struct sk_buff *skb, __be32 saddr, __be32 daddr, struct rtmsg *rtm, u32 portid); + +#ifdef CONFIG_IP_MROUTE +void ipmr_cache_free(struct mfc_cache *mfc_cache); +#else +static inline void ipmr_cache_free(struct mfc_cache *mfc_cache) +{ +} +#endif + +static inline void ipmr_cache_put(struct mfc_cache *c) +{ + if (refcount_dec_and_test(&c->mfc_un.res.refcount)) + ipmr_cache_free(c); +} +static inline void ipmr_cache_hold(struct mfc_cache *c) +{ + refcount_inc(&c->mfc_un.res.refcount); +} + #endif diff --git a/include/net/fib_notifier.h b/include/net/fib_notifier.h index 669b9716dc7a..54cd6b839d2f 100644 --- a/include/net/fib_notifier.h +++ b/include/net/fib_notifier.h @@ -20,6 +20,8 @@ enum fib_event_type { FIB_EVENT_RULE_DEL, FIB_EVENT_NH_ADD, FIB_EVENT_NH_DEL, + FIB_EVENT_VIF_ADD, + FIB_EVENT_VIF_DEL, }; struct fib_notifier_ops { diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 8387f099115e..abc84d986da4 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -163,6 +163,9 @@ struct netns_ipv4 { struct fib_notifier_ops *notifier_ops; unsigned int fib_seq; /* protected by rtnl_mutex */ + struct fib_notifier_ops *ipmr_notifier_ops; + unsigned int ipmr_seq; /* protected by rtnl_mutex */ + atomic_t rt_genid; }; #endif |
