aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-03-26 13:14:45 -0400
committerDavid S. Miller <davem@davemloft.net>2018-03-26 13:14:45 -0400
commit336f2c038da1b7f3faf098f2f61bca51e19089ad (patch)
tree57707e2ab40612d2bb2d2ee5162c0e62dddf126d /include/linux
parentMerge branch 'pernet-convert-part7.1' (diff)
parentmlxsw: spectrum: Add multicast router trap for PIMv6 (diff)
Merge branch 'mlxsw-Offload-IPv6-multicast-routes'
Ido Schimmel says: ==================== mlxsw: Offload IPv6 multicast routes Yuval says: The series is intended to allow offloading IPv6 multicast routes and is split into two parts: - First half of the patches continue extending ip6mr [& refactor ipmr] with missing bits necessary for the offloading - fib-notifications, mfc refcounting and default rule identification. - Second half of the patches extend functionality inside mlxsw, beginning with extending lower-parts to support IPv6 mroutes to host and later extending the router/mr internal APIs within the driver to accommodate support in ipv6 configurations. Lastly it adds support in the RTNL_FAMILY_IP6MR notifications, allowing driver to react and offload related routes. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/mroute.h33
-rw-r--r--include/linux/mroute6.h10
-rw-r--r--include/linux/mroute_base.h128
3 files changed, 138 insertions, 33 deletions
diff --git a/include/linux/mroute.h b/include/linux/mroute.h
index 7ed82e4f11b3..9a36fad9e068 100644
--- a/include/linux/mroute.h
+++ b/include/linux/mroute.h
@@ -55,14 +55,6 @@ static inline bool ipmr_rule_default(const struct fib_rule *rule)
}
#endif
-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
struct mfc_cache_cmp_arg {
@@ -88,33 +80,8 @@ struct mfc_cache {
};
};
-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->_c.mfc_un.res.refcount))
- ipmr_cache_free(c);
-}
-static inline void ipmr_cache_hold(struct mfc_cache *c)
-{
- refcount_inc(&c->_c.mfc_un.res.refcount);
-}
-
#endif
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index 1ac38e6819f5..c4a45859f586 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -8,6 +8,7 @@
#include <net/net_namespace.h>
#include <uapi/linux/mroute6.h>
#include <linux/mroute_base.h>
+#include <net/fib_rules.h>
#ifdef CONFIG_IPV6_MROUTE
static inline int ip6_mroute_opt(int opt)
@@ -63,6 +64,15 @@ static inline void ip6_mr_cleanup(void)
}
#endif
+#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
+bool ip6mr_rule_default(const struct fib_rule *rule);
+#else
+static inline bool ip6mr_rule_default(const struct fib_rule *rule)
+{
+ return true;
+}
+#endif
+
#define VIFF_STATIC 0x8000
struct mfc6_cache_cmp_arg {
diff --git a/include/linux/mroute_base.h b/include/linux/mroute_base.h
index c2560cb50f1d..d617fe45543e 100644
--- a/include/linux/mroute_base.h
+++ b/include/linux/mroute_base.h
@@ -6,6 +6,7 @@
#include <linux/spinlock.h>
#include <net/net_namespace.h>
#include <net/sock.h>
+#include <net/fib_notifier.h>
/**
* struct vif_device - interface representor for multicast routing
@@ -36,6 +37,58 @@ struct vif_device {
__be32 local, remote;
};
+struct vif_entry_notifier_info {
+ struct fib_notifier_info info;
+ struct net_device *dev;
+ unsigned short vif_index;
+ unsigned short vif_flags;
+ u32 tb_id;
+};
+
+static inline int mr_call_vif_notifier(struct notifier_block *nb,
+ struct net *net,
+ unsigned short family,
+ enum fib_event_type event_type,
+ struct vif_device *vif,
+ unsigned short vif_index, u32 tb_id)
+{
+ struct vif_entry_notifier_info info = {
+ .info = {
+ .family = family,
+ .net = net,
+ },
+ .dev = vif->dev,
+ .vif_index = vif_index,
+ .vif_flags = vif->flags,
+ .tb_id = tb_id,
+ };
+
+ return call_fib_notifier(nb, net, event_type, &info.info);
+}
+
+static inline int mr_call_vif_notifiers(struct net *net,
+ unsigned short family,
+ enum fib_event_type event_type,
+ struct vif_device *vif,
+ unsigned short vif_index, u32 tb_id,
+ unsigned int *ipmr_seq)
+{
+ struct vif_entry_notifier_info info = {
+ .info = {
+ .family = family,
+ .net = net,
+ },
+ .dev = vif->dev,
+ .vif_index = vif_index,
+ .vif_flags = vif->flags,
+ .tb_id = tb_id,
+ };
+
+ ASSERT_RTNL();
+ (*ipmr_seq)++;
+ return call_fib_notifiers(net, event_type, &info.info);
+}
+
#ifndef MAXVIFS
/* This one is nasty; value is defined in uapi using different symbols for
* mroute and morute6 but both map into same 32.
@@ -72,6 +125,7 @@ enum {
* @refcount: reference count for this entry
* @list: global entry list
* @rcu: used for entry destruction
+ * @free: Operation used for freeing an entry under RCU
*/
struct mr_mfc {
struct rhlist_head mnode;
@@ -97,8 +151,64 @@ struct mr_mfc {
} mfc_un;
struct list_head list;
struct rcu_head rcu;
+ void (*free)(struct rcu_head *head);
+};
+
+static inline void mr_cache_put(struct mr_mfc *c)
+{
+ if (refcount_dec_and_test(&c->mfc_un.res.refcount))
+ call_rcu(&c->rcu, c->free);
+}
+
+static inline void mr_cache_hold(struct mr_mfc *c)
+{
+ refcount_inc(&c->mfc_un.res.refcount);
+}
+
+struct mfc_entry_notifier_info {
+ struct fib_notifier_info info;
+ struct mr_mfc *mfc;
+ u32 tb_id;
};
+static inline int mr_call_mfc_notifier(struct notifier_block *nb,
+ struct net *net,
+ unsigned short family,
+ enum fib_event_type event_type,
+ struct mr_mfc *mfc, u32 tb_id)
+{
+ struct mfc_entry_notifier_info info = {
+ .info = {
+ .family = family,
+ .net = net,
+ },
+ .mfc = mfc,
+ .tb_id = tb_id
+ };
+
+ return call_fib_notifier(nb, net, event_type, &info.info);
+}
+
+static inline int mr_call_mfc_notifiers(struct net *net,
+ unsigned short family,
+ enum fib_event_type event_type,
+ struct mr_mfc *mfc, u32 tb_id,
+ unsigned int *ipmr_seq)
+{
+ struct mfc_entry_notifier_info info = {
+ .info = {
+ .family = family,
+ .net = net,
+ },
+ .mfc = mfc,
+ .tb_id = tb_id
+ };
+
+ ASSERT_RTNL();
+ (*ipmr_seq)++;
+ return call_fib_notifiers(net, event_type, &info.info);
+}
+
struct mr_table;
/**
@@ -180,6 +290,13 @@ int mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
u32 portid, u32 seq, struct mr_mfc *c,
int cmd, int flags),
spinlock_t *lock);
+
+int mr_dump(struct net *net, struct notifier_block *nb, unsigned short family,
+ int (*rules_dump)(struct net *net,
+ struct notifier_block *nb),
+ struct mr_table *(*mr_iter)(struct net *net,
+ struct mr_table *mrt),
+ rwlock_t *mrt_lock);
#else
static inline void vif_device_init(struct vif_device *v,
struct net_device *dev,
@@ -236,6 +353,17 @@ mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb,
{
return -EINVAL;
}
+
+static inline int mr_dump(struct net *net, struct notifier_block *nb,
+ unsigned short family,
+ int (*rules_dump)(struct net *net,
+ struct notifier_block *nb),
+ struct mr_table *(*mr_iter)(struct net *net,
+ struct mr_table *mrt),
+ rwlock_t *mrt_lock)
+{
+ return -EINVAL;
+}
#endif
static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)