* [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes
@ 2017-12-15 18:27 Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 1/6] lwt: Add net to build_state argument Tom Herbert
` (5 more replies)
0 siblings, 6 replies; 12+ messages in thread
From: Tom Herbert @ 2017-12-15 18:27 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
This patch set adds support to get netlink notifications for ILA
routes when a route is used. This is done to support ILA forwarding
cache address resolution as well as ILA router redirect mechanisms.
This patch set contains:
- The ILA route notification mechanism
- Routing messages are used over netlink to indicate resolution
requests
- Add net to ila build_state
- Add flush command to ila_xlat
- Fix use of rhashtable for latest fixes
v4:
- Remove front end cache per davem feedback
- Eliminate separate LWT type just use ILA LWT already in place
v3:
- Removed rhashtable changes to their own patch set
- Restructure ILA code to be more amenable to changes
- Remove extra call back functions in resolution interface
Changes from initial RFC:
- Added net argument to LWT build_state
- Made resolve timeout an attribute of the LWT encap route
- Changed ILA notifications to be regular routing messages of event
RTM_ADDR_RESOLVE, family RTNL_FAMILY_ILA, and group
RTNLGRP_ILA_NOTIFY
Tom Herbert (6):
lwt: Add net to build_state argument
ila: Fix use of rhashtable walk in ila_xlat.c
ila: Call library function alloc_bucket_locks
ila: create main ila source file
ila: Flush netlink command to clear xlat table
ila: Route notify
include/net/lwtunnel.h | 6 +-
include/uapi/linux/ila.h | 3 +
include/uapi/linux/rtnetlink.h | 8 +-
net/core/lwt_bpf.c | 2 +-
net/core/lwtunnel.c | 4 +-
net/ipv4/fib_semantics.c | 13 +-
net/ipv4/ip_tunnel_core.c | 4 +-
net/ipv6/ila/Makefile | 2 +-
net/ipv6/ila/ila.h | 27 +++-
net/ipv6/ila/ila_common.c | 30 -----
net/ipv6/ila/ila_lwt.c | 270 ++++++++++++++++++++++++++------------
net/ipv6/ila/ila_main.c | 121 +++++++++++++++++
net/ipv6/ila/ila_xlat.c | 290 ++++++++++++++++++++---------------------
net/ipv6/route.c | 2 +-
net/ipv6/seg6_iptunnel.c | 2 +-
net/ipv6/seg6_local.c | 5 +-
net/mpls/mpls_iptunnel.c | 2 +-
17 files changed, 508 insertions(+), 283 deletions(-)
create mode 100644 net/ipv6/ila/ila_main.c
--
2.11.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v4 net-next 1/6] lwt: Add net to build_state argument
2017-12-15 18:27 [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes Tom Herbert
@ 2017-12-15 18:27 ` Tom Herbert
2017-12-19 15:47 ` Roopa Prabhu
2017-12-15 18:27 ` [PATCH v4 net-next 2/6] ila: Fix use of rhashtable walk in ila_xlat.c Tom Herbert
` (4 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Tom Herbert @ 2017-12-15 18:27 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
Users of LWT need to know net if they want to have per net operations
in LWT.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/net/lwtunnel.h | 6 +++---
net/core/lwt_bpf.c | 2 +-
net/core/lwtunnel.c | 4 ++--
net/ipv4/fib_semantics.c | 13 ++++++++-----
net/ipv4/ip_tunnel_core.c | 4 ++--
net/ipv6/ila/ila_lwt.c | 2 +-
net/ipv6/route.c | 2 +-
net/ipv6/seg6_iptunnel.c | 2 +-
net/ipv6/seg6_local.c | 5 +++--
net/mpls/mpls_iptunnel.c | 2 +-
10 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
index d747ef975cd8..da5e51e0d122 100644
--- a/include/net/lwtunnel.h
+++ b/include/net/lwtunnel.h
@@ -34,7 +34,7 @@ struct lwtunnel_state {
};
struct lwtunnel_encap_ops {
- int (*build_state)(struct nlattr *encap,
+ int (*build_state)(struct net *net, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack);
@@ -113,7 +113,7 @@ int lwtunnel_valid_encap_type(u16 encap_type,
struct netlink_ext_ack *extack);
int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
struct netlink_ext_ack *extack);
-int lwtunnel_build_state(u16 encap_type,
+int lwtunnel_build_state(struct net *net, u16 encap_type,
struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **lws,
@@ -192,7 +192,7 @@ static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
return 0;
}
-static inline int lwtunnel_build_state(u16 encap_type,
+static inline int lwtunnel_build_state(struct net *net, u16 encap_type,
struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **lws,
diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
index e7e626fb87bb..3a3ac13fcf06 100644
--- a/net/core/lwt_bpf.c
+++ b/net/core/lwt_bpf.c
@@ -238,7 +238,7 @@ static const struct nla_policy bpf_nl_policy[LWT_BPF_MAX + 1] = {
[LWT_BPF_XMIT_HEADROOM] = { .type = NLA_U32 },
};
-static int bpf_build_state(struct nlattr *nla,
+static int bpf_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 0b171756453c..b3f2f77dfe72 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -103,7 +103,7 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops,
}
EXPORT_SYMBOL_GPL(lwtunnel_encap_del_ops);
-int lwtunnel_build_state(u16 encap_type,
+int lwtunnel_build_state(struct net *net, u16 encap_type,
struct nlattr *encap, unsigned int family,
const void *cfg, struct lwtunnel_state **lws,
struct netlink_ext_ack *extack)
@@ -124,7 +124,7 @@ int lwtunnel_build_state(u16 encap_type,
ops = rcu_dereference(lwtun_encaps[encap_type]);
if (likely(ops && ops->build_state && try_module_get(ops->owner))) {
found = true;
- ret = ops->build_state(encap, family, cfg, lws, extack);
+ ret = ops->build_state(net, encap, family, cfg, lws, extack);
if (ret)
module_put(ops->owner);
}
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index f04d944f8abe..4979e5c6b9b8 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -523,6 +523,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
if (nla) {
struct lwtunnel_state *lwtstate;
struct nlattr *nla_entype;
+ struct net *net = cfg->fc_nlinfo.nl_net;
nla_entype = nla_find(attrs, attrlen,
RTA_ENCAP_TYPE);
@@ -533,7 +534,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
goto err_inval;
}
- ret = lwtunnel_build_state(nla_get_u16(
+ ret = lwtunnel_build_state(net, nla_get_u16(
nla_entype),
nla, AF_INET, cfg,
&lwtstate, extack);
@@ -607,7 +608,7 @@ static void fib_rebalance(struct fib_info *fi)
#endif /* CONFIG_IP_ROUTE_MULTIPATH */
-static int fib_encap_match(u16 encap_type,
+static int fib_encap_match(struct net *net, u16 encap_type,
struct nlattr *encap,
const struct fib_nh *nh,
const struct fib_config *cfg,
@@ -619,7 +620,7 @@ static int fib_encap_match(u16 encap_type,
if (encap_type == LWTUNNEL_ENCAP_NONE)
return 0;
- ret = lwtunnel_build_state(encap_type, encap, AF_INET,
+ ret = lwtunnel_build_state(net, encap_type, encap, AF_INET,
cfg, &lwtstate, extack);
if (!ret) {
result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate);
@@ -632,6 +633,7 @@ static int fib_encap_match(u16 encap_type,
int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
struct netlink_ext_ack *extack)
{
+ struct net *net = cfg->fc_nlinfo.nl_net;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
struct rtnexthop *rtnh;
int remaining;
@@ -642,7 +644,8 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
if (cfg->fc_oif || cfg->fc_gw) {
if (cfg->fc_encap) {
- if (fib_encap_match(cfg->fc_encap_type, cfg->fc_encap,
+ if (fib_encap_match(net, cfg->fc_encap_type,
+ cfg->fc_encap,
fi->fib_nh, cfg, extack))
return 1;
}
@@ -1180,7 +1183,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
"LWT encap type not specified");
goto err_inval;
}
- err = lwtunnel_build_state(cfg->fc_encap_type,
+ err = lwtunnel_build_state(net, cfg->fc_encap_type,
cfg->fc_encap, AF_INET, cfg,
&lwtstate, extack);
if (err)
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 2f39479be92f..32e05aa6117d 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -228,7 +228,7 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = {
[LWTUNNEL_IP_FLAGS] = { .type = NLA_U16 },
};
-static int ip_tun_build_state(struct nlattr *attr,
+static int ip_tun_build_state(struct net *net, struct nlattr *attr,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
@@ -327,7 +327,7 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
[LWTUNNEL_IP6_FLAGS] = { .type = NLA_U16 },
};
-static int ip6_tun_build_state(struct nlattr *attr,
+static int ip6_tun_build_state(struct net *net, struct nlattr *attr,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 3d56a2fb6f86..9f1e46a1468e 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -125,7 +125,7 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
[ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8, },
};
-static int ila_build_state(struct nlattr *nla,
+static int ila_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b3f4d19b3ca5..0e0cc97e8f42 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2565,7 +2565,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
if (cfg->fc_encap) {
struct lwtunnel_state *lwtstate;
- err = lwtunnel_build_state(cfg->fc_encap_type,
+ err = lwtunnel_build_state(net, cfg->fc_encap_type,
cfg->fc_encap, AF_INET6, cfg,
&lwtstate, extack);
if (err)
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index bd6cc688bd19..a6cf2fba15f3 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -359,7 +359,7 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
return err;
}
-static int seg6_build_state(struct nlattr *nla,
+static int seg6_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 825b8e01f947..45dc670c5a93 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -779,8 +779,9 @@ static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)
return 0;
}
-static int seg6_local_build_state(struct nlattr *nla, unsigned int family,
- const void *cfg, struct lwtunnel_state **ts,
+static int seg6_local_build_state(struct net *net, struct nlattr *nla,
+ unsigned int family, const void *cfg,
+ struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{
struct nlattr *tb[SEG6_LOCAL_MAX + 1];
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c
index 6e558a419f60..c947310cc04f 100644
--- a/net/mpls/mpls_iptunnel.c
+++ b/net/mpls/mpls_iptunnel.c
@@ -157,7 +157,7 @@ static int mpls_xmit(struct sk_buff *skb)
return -EINVAL;
}
-static int mpls_build_state(struct nlattr *nla,
+static int mpls_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 net-next 2/6] ila: Fix use of rhashtable walk in ila_xlat.c
2017-12-15 18:27 [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 1/6] lwt: Add net to build_state argument Tom Herbert
@ 2017-12-15 18:27 ` Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 3/6] ila: Call library function alloc_bucket_locks Tom Herbert
` (3 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Tom Herbert @ 2017-12-15 18:27 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
Perform better EAGAIN handling, handle case where ila_dump_info
fails and we missed objects in the dump, and add a skip index
to skip over ila entires in a list on a rhashtable node that have
already been visited (by a previous call to ila_nl_dump).
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
net/ipv6/ila/ila_xlat.c | 70 ++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 54 insertions(+), 16 deletions(-)
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 44c39c5f0638..887dd5b785b5 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -474,24 +474,31 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
struct ila_dump_iter {
struct rhashtable_iter rhiter;
+ int skip;
};
static int ila_nl_dump_start(struct netlink_callback *cb)
{
struct net *net = sock_net(cb->skb->sk);
struct ila_net *ilan = net_generic(net, ila_net_id);
- struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
+ struct ila_dump_iter *iter;
+ int ret;
- if (!iter) {
- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
- if (!iter)
- return -ENOMEM;
+ iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ if (!iter)
+ return -ENOMEM;
- cb->args[0] = (long)iter;
+ ret = rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
+ GFP_KERNEL);
+ if (ret) {
+ kfree(iter);
+ return ret;
}
- return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
- GFP_KERNEL);
+ iter->skip = 0;
+ cb->args[0] = (long)iter;
+
+ return ret;
}
static int ila_nl_dump_done(struct netlink_callback *cb)
@@ -509,20 +516,45 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
struct rhashtable_iter *rhiter = &iter->rhiter;
+ int skip = iter->skip;
struct ila_map *ila;
int ret;
rhashtable_walk_start(rhiter);
- for (;;) {
- ila = rhashtable_walk_next(rhiter);
+ /* Get first entry */
+ ila = rhashtable_walk_peek(rhiter);
+
+ if (ila && !IS_ERR(ila) && skip) {
+ /* Skip over visited entries */
+
+ while (ila && skip) {
+ /* Skip over any ila entries in this list that we
+ * have already dumped.
+ */
+ ila = rcu_access_pointer(ila->next);
+ skip--;
+ }
+ }
+ skip = 0;
+
+ for (;;) {
if (IS_ERR(ila)) {
- if (PTR_ERR(ila) == -EAGAIN)
- continue;
ret = PTR_ERR(ila);
- goto done;
+ if (ret == -EAGAIN) {
+ /* Table has changed and iter has reset. Return
+ * -EAGAIN to the application even if we have
+ * written data to the skb. The application
+ * needs to deal with this.
+ */
+
+ goto out_ret;
+ } else {
+ break;
+ }
} else if (!ila) {
+ ret = 0;
break;
}
@@ -531,15 +563,21 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
cb->nlh->nlmsg_seq, NLM_F_MULTI,
skb, ILA_CMD_GET);
if (ret)
- goto done;
+ goto out;
+ skip++;
ila = rcu_access_pointer(ila->next);
}
+
+ skip = 0;
+ ila = rhashtable_walk_next(rhiter);
}
- ret = skb->len;
+out:
+ iter->skip = skip;
+ ret = (skb->len ? : ret);
-done:
+out_ret:
rhashtable_walk_stop(rhiter);
return ret;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 net-next 3/6] ila: Call library function alloc_bucket_locks
2017-12-15 18:27 [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 1/6] lwt: Add net to build_state argument Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 2/6] ila: Fix use of rhashtable walk in ila_xlat.c Tom Herbert
@ 2017-12-15 18:27 ` Tom Herbert
2017-12-16 20:47 ` kbuild test robot
2017-12-15 18:27 ` [PATCH v4 net-next 4/6] ila: create main ila source file Tom Herbert
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Tom Herbert @ 2017-12-15 18:27 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
To allocate the array of bucket locks for the hash table we now
call library function alloc_bucket_spinlocks.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
net/ipv6/ila/ila_xlat.c | 22 +++++-----------------
1 file changed, 5 insertions(+), 17 deletions(-)
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 887dd5b785b5..3ef8869ac508 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -31,26 +31,14 @@ struct ila_net {
bool hooks_registered;
};
+#define MAX_LOCKS 1024
#define LOCKS_PER_CPU 10
static int alloc_ila_locks(struct ila_net *ilan)
{
- unsigned int i, size;
- unsigned int nr_pcpus = num_possible_cpus();
-
- nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL);
- size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU);
-
- if (sizeof(spinlock_t) != 0) {
- ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL);
- if (!ilan->locks)
- return -ENOMEM;
- for (i = 0; i < size; i++)
- spin_lock_init(&ilan->locks[i]);
- }
- ilan->locks_mask = size - 1;
-
- return 0;
+ return alloc_bucket_spinlocks(&ilan->xlat.locks, &ilan->xlat.locks_mask,
+ MAX_LOCKS, LOCKS_PER_CPU,
+ GFP_KERNEL);
}
static u32 hashrnd __read_mostly;
@@ -639,7 +627,7 @@ static __net_exit void ila_exit_net(struct net *net)
rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL);
- kvfree(ilan->locks);
+ free_bucket_spinlocks(ilan->xlat.locks);
if (ilan->hooks_registered)
nf_unregister_net_hooks(net, ila_nf_hook_ops,
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 net-next 4/6] ila: create main ila source file
2017-12-15 18:27 [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes Tom Herbert
` (2 preceding siblings ...)
2017-12-15 18:27 ` [PATCH v4 net-next 3/6] ila: Call library function alloc_bucket_locks Tom Herbert
@ 2017-12-15 18:27 ` Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 5/6] ila: Flush netlink command to clear xlat table Tom Herbert
2017-12-15 18:28 ` [PATCH v4 net-next 6/6] ila: Route notify Tom Herbert
5 siblings, 0 replies; 12+ messages in thread
From: Tom Herbert @ 2017-12-15 18:27 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
Create a main ila file that contains the module initialization functions
as well as netlink definitions. Previously these were defined in
ila_xlat and ila_common. This approach allows better extensibility.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
net/ipv6/ila/Makefile | 2 +-
net/ipv6/ila/ila.h | 26 ++++++++-
net/ipv6/ila/ila_common.c | 30 ----------
net/ipv6/ila/ila_main.c | 115 ++++++++++++++++++++++++++++++++++++++
net/ipv6/ila/ila_xlat.c | 138 +++++++++-------------------------------------
5 files changed, 166 insertions(+), 145 deletions(-)
create mode 100644 net/ipv6/ila/ila_main.c
diff --git a/net/ipv6/ila/Makefile b/net/ipv6/ila/Makefile
index 4b32e5921e5c..b7739aba6e68 100644
--- a/net/ipv6/ila/Makefile
+++ b/net/ipv6/ila/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_IPV6_ILA) += ila.o
-ila-objs := ila_common.o ila_lwt.o ila_xlat.o
+ila-objs := ila_main.o ila_common.o ila_lwt.o ila_xlat.o
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index 3c7a11b62334..faba7824ea56 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -19,6 +19,7 @@
#include <linux/skbuff.h>
#include <linux/types.h>
#include <net/checksum.h>
+#include <net/genetlink.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <uapi/linux/ila.h>
@@ -104,9 +105,30 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p,
void ila_init_saved_csum(struct ila_params *p);
+struct ila_net {
+ struct {
+ struct rhashtable rhash_table;
+ spinlock_t *locks; /* Bucket locks for entry manipulation */
+ unsigned int locks_mask;
+ bool hooks_registered;
+ } xlat;
+};
+
int ila_lwt_init(void);
void ila_lwt_fini(void);
-int ila_xlat_init(void);
-void ila_xlat_fini(void);
+
+int ila_xlat_init_net(struct net *net);
+void ila_xlat_exit_net(struct net *net);
+
+int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_dump_start(struct netlink_callback *cb);
+int ila_xlat_nl_dump_done(struct netlink_callback *cb);
+int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
+extern unsigned int ila_net_id;
+
+extern struct genl_family ila_nl_family;
#endif /* __ILA_H */
diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c
index 8c88ecf29b93..579310466eac 100644
--- a/net/ipv6/ila/ila_common.c
+++ b/net/ipv6/ila/ila_common.c
@@ -154,33 +154,3 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p,
iaddr->loc = p->locator;
}
-static int __init ila_init(void)
-{
- int ret;
-
- ret = ila_lwt_init();
-
- if (ret)
- goto fail_lwt;
-
- ret = ila_xlat_init();
- if (ret)
- goto fail_xlat;
-
- return 0;
-fail_xlat:
- ila_lwt_fini();
-fail_lwt:
- return ret;
-}
-
-static void __exit ila_fini(void)
-{
- ila_xlat_fini();
- ila_lwt_fini();
-}
-
-module_init(ila_init);
-module_exit(ila_fini);
-MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>");
-MODULE_LICENSE("GPL");
diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c
new file mode 100644
index 000000000000..f6ac6b14577e
--- /dev/null
+++ b/net/ipv6/ila/ila_main.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <net/genetlink.h>
+#include <net/ila.h>
+#include <net/netns/generic.h>
+#include <uapi/linux/genetlink.h>
+#include "ila.h"
+
+static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
+ [ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
+ [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
+ [ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
+ [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
+ [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
+};
+
+static const struct genl_ops ila_nl_ops[] = {
+ {
+ .cmd = ILA_CMD_ADD,
+ .doit = ila_xlat_nl_cmd_add_mapping,
+ .policy = ila_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = ILA_CMD_DEL,
+ .doit = ila_xlat_nl_cmd_del_mapping,
+ .policy = ila_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = ILA_CMD_GET,
+ .doit = ila_xlat_nl_cmd_get_mapping,
+ .start = ila_xlat_nl_dump_start,
+ .dumpit = ila_xlat_nl_dump,
+ .done = ila_xlat_nl_dump_done,
+ .policy = ila_nl_policy,
+ },
+};
+
+unsigned int ila_net_id;
+
+struct genl_family ila_nl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = ILA_GENL_NAME,
+ .version = ILA_GENL_VERSION,
+ .maxattr = ILA_ATTR_MAX,
+ .netnsok = true,
+ .parallel_ops = true,
+ .module = THIS_MODULE,
+ .ops = ila_nl_ops,
+ .n_ops = ARRAY_SIZE(ila_nl_ops),
+};
+
+static __net_init int ila_init_net(struct net *net)
+{
+ int err;
+
+ err = ila_xlat_init_net(net);
+ if (err)
+ goto ila_xlat_init_fail;
+
+ return 0;
+
+ila_xlat_init_fail:
+ return err;
+}
+
+static __net_exit void ila_exit_net(struct net *net)
+{
+ ila_xlat_exit_net(net);
+}
+
+static struct pernet_operations ila_net_ops = {
+ .init = ila_init_net,
+ .exit = ila_exit_net,
+ .id = &ila_net_id,
+ .size = sizeof(struct ila_net),
+};
+
+static int __init ila_init(void)
+{
+ int ret;
+
+ ret = register_pernet_device(&ila_net_ops);
+ if (ret)
+ goto register_device_fail;
+
+ ret = genl_register_family(&ila_nl_family);
+ if (ret)
+ goto register_family_fail;
+
+ ret = ila_lwt_init();
+ if (ret)
+ goto fail_lwt;
+
+ return 0;
+
+fail_lwt:
+ genl_unregister_family(&ila_nl_family);
+register_family_fail:
+ unregister_pernet_device(&ila_net_ops);
+register_device_fail:
+ return ret;
+}
+
+static void __exit ila_fini(void)
+{
+ ila_lwt_fini();
+ genl_unregister_family(&ila_nl_family);
+ unregister_pernet_device(&ila_net_ops);
+}
+
+module_init(ila_init);
+module_exit(ila_fini);
+MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>");
+MODULE_LICENSE("GPL");
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 3ef8869ac508..d05de891dfb6 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -22,15 +22,6 @@ struct ila_map {
struct rcu_head rcu;
};
-static unsigned int ila_net_id;
-
-struct ila_net {
- struct rhashtable rhash_table;
- spinlock_t *locks; /* Bucket locks for entry manipulation */
- unsigned int locks_mask;
- bool hooks_registered;
-};
-
#define MAX_LOCKS 1024
#define LOCKS_PER_CPU 10
@@ -58,7 +49,7 @@ static inline u32 ila_locator_hash(struct ila_locator loc)
static inline spinlock_t *ila_get_lock(struct ila_net *ilan,
struct ila_locator loc)
{
- return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask];
+ return &ilan->xlat.locks[ila_locator_hash(loc) & ilan->xlat.locks_mask];
}
static inline int ila_cmp_wildcards(struct ila_map *ila,
@@ -102,16 +93,6 @@ static const struct rhashtable_params rht_params = {
.obj_cmpfn = ila_cmpfn,
};
-static struct genl_family ila_nl_family;
-
-static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
- [ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
- [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
- [ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
- [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
- [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
-};
-
static int parse_nl_config(struct genl_info *info,
struct ila_xlat_params *xp)
{
@@ -149,7 +130,7 @@ static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr,
{
struct ila_map *ila;
- ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc,
+ ila = rhashtable_lookup_fast(&ilan->xlat.rhash_table, &iaddr->loc,
rht_params);
while (ila) {
if (!ila_cmp_wildcards(ila, iaddr, ifindex))
@@ -166,7 +147,7 @@ static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp,
{
struct ila_map *ila;
- ila = rhashtable_lookup_fast(&ilan->rhash_table,
+ ila = rhashtable_lookup_fast(&ilan->xlat.rhash_table,
&xp->ip.locator_match,
rht_params);
while (ila) {
@@ -222,7 +203,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
int err = 0, order;
- if (!ilan->hooks_registered) {
+ if (!ilan->xlat.hooks_registered) {
/* We defer registering net hooks in the namespace until the
* first mapping is added.
*/
@@ -231,7 +212,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
if (err)
return err;
- ilan->hooks_registered = true;
+ ilan->xlat.hooks_registered = true;
}
ila = kzalloc(sizeof(*ila), GFP_KERNEL);
@@ -246,12 +227,12 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
spin_lock(lock);
- head = rhashtable_lookup_fast(&ilan->rhash_table,
+ head = rhashtable_lookup_fast(&ilan->xlat.rhash_table,
&xp->ip.locator_match,
rht_params);
if (!head) {
/* New entry for the rhash_table */
- err = rhashtable_lookup_insert_fast(&ilan->rhash_table,
+ err = rhashtable_lookup_insert_fast(&ilan->xlat.rhash_table,
&ila->node, rht_params);
} else {
struct ila_map *tila = head, *prev = NULL;
@@ -277,7 +258,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
} else {
/* Make this ila new head */
RCU_INIT_POINTER(ila->next, head);
- err = rhashtable_replace_fast(&ilan->rhash_table,
+ err = rhashtable_replace_fast(&ilan->xlat.rhash_table,
&head->node,
&ila->node, rht_params);
if (err)
@@ -303,7 +284,7 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
spin_lock(lock);
- head = rhashtable_lookup_fast(&ilan->rhash_table,
+ head = rhashtable_lookup_fast(&ilan->xlat.rhash_table,
&xp->ip.locator_match, rht_params);
ila = head;
@@ -333,15 +314,15 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
* table
*/
err = rhashtable_replace_fast(
- &ilan->rhash_table, &ila->node,
+ &ilan->xlat.rhash_table, &ila->node,
&head->node, rht_params);
if (err)
goto out;
} else {
/* Entry no longer used */
- err = rhashtable_remove_fast(&ilan->rhash_table,
- &ila->node,
- rht_params);
+ err = rhashtable_remove_fast(
+ &ilan->xlat.rhash_table,
+ &ila->node, rht_params);
}
}
@@ -356,7 +337,7 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
return err;
}
-static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
+int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct ila_xlat_params p;
@@ -369,7 +350,7 @@ static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
return ila_add_mapping(net, &p);
}
-static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
+int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct ila_xlat_params xp;
@@ -421,7 +402,7 @@ static int ila_dump_info(struct ila_map *ila,
return -EMSGSIZE;
}
-static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
+int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct ila_net *ilan = net_generic(net, ila_net_id);
@@ -465,7 +446,7 @@ struct ila_dump_iter {
int skip;
};
-static int ila_nl_dump_start(struct netlink_callback *cb)
+int ila_xlat_nl_dump_start(struct netlink_callback *cb)
{
struct net *net = sock_net(cb->skb->sk);
struct ila_net *ilan = net_generic(net, ila_net_id);
@@ -476,7 +457,7 @@ static int ila_nl_dump_start(struct netlink_callback *cb)
if (!iter)
return -ENOMEM;
- ret = rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
+ ret = rhashtable_walk_init(&ilan->xlat.rhash_table, &iter->rhiter,
GFP_KERNEL);
if (ret) {
kfree(iter);
@@ -489,7 +470,7 @@ static int ila_nl_dump_start(struct netlink_callback *cb)
return ret;
}
-static int ila_nl_dump_done(struct netlink_callback *cb)
+int ila_xlat_nl_dump_done(struct netlink_callback *cb)
{
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
@@ -500,7 +481,7 @@ static int ila_nl_dump_done(struct netlink_callback *cb)
return 0;
}
-static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
+int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
struct rhashtable_iter *rhiter = &iter->rhiter;
@@ -570,77 +551,35 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
return ret;
}
-static const struct genl_ops ila_nl_ops[] = {
- {
- .cmd = ILA_CMD_ADD,
- .doit = ila_nl_cmd_add_mapping,
- .policy = ila_nl_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = ILA_CMD_DEL,
- .doit = ila_nl_cmd_del_mapping,
- .policy = ila_nl_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = ILA_CMD_GET,
- .doit = ila_nl_cmd_get_mapping,
- .start = ila_nl_dump_start,
- .dumpit = ila_nl_dump,
- .done = ila_nl_dump_done,
- .policy = ila_nl_policy,
- },
-};
-
-static struct genl_family ila_nl_family __ro_after_init = {
- .hdrsize = 0,
- .name = ILA_GENL_NAME,
- .version = ILA_GENL_VERSION,
- .maxattr = ILA_ATTR_MAX,
- .netnsok = true,
- .parallel_ops = true,
- .module = THIS_MODULE,
- .ops = ila_nl_ops,
- .n_ops = ARRAY_SIZE(ila_nl_ops),
-};
-
#define ILA_HASH_TABLE_SIZE 1024
-static __net_init int ila_init_net(struct net *net)
+int ila_xlat_init_net(struct net *net)
{
- int err;
struct ila_net *ilan = net_generic(net, ila_net_id);
+ int err;
err = alloc_ila_locks(ilan);
if (err)
return err;
- rhashtable_init(&ilan->rhash_table, &rht_params);
+ rhashtable_init(&ilan->xlat.rhash_table, &rht_params);
return 0;
}
-static __net_exit void ila_exit_net(struct net *net)
+void ila_xlat_exit_net(struct net *net)
{
struct ila_net *ilan = net_generic(net, ila_net_id);
- rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL);
+ rhashtable_free_and_destroy(&ilan->xlat.rhash_table, ila_free_cb, NULL);
free_bucket_spinlocks(ilan->xlat.locks);
- if (ilan->hooks_registered)
+ if (ilan->xlat.hooks_registered)
nf_unregister_net_hooks(net, ila_nf_hook_ops,
ARRAY_SIZE(ila_nf_hook_ops));
}
-static struct pernet_operations ila_net_ops = {
- .init = ila_init_net,
- .exit = ila_exit_net,
- .id = &ila_net_id,
- .size = sizeof(struct ila_net),
-};
-
static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila)
{
struct ila_map *ila;
@@ -667,28 +606,3 @@ static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila)
return 0;
}
-int __init ila_xlat_init(void)
-{
- int ret;
-
- ret = register_pernet_device(&ila_net_ops);
- if (ret)
- goto exit;
-
- ret = genl_register_family(&ila_nl_family);
- if (ret < 0)
- goto unregister;
-
- return 0;
-
-unregister:
- unregister_pernet_device(&ila_net_ops);
-exit:
- return ret;
-}
-
-void ila_xlat_fini(void)
-{
- genl_unregister_family(&ila_nl_family);
- unregister_pernet_device(&ila_net_ops);
-}
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 net-next 5/6] ila: Flush netlink command to clear xlat table
2017-12-15 18:27 [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes Tom Herbert
` (3 preceding siblings ...)
2017-12-15 18:27 ` [PATCH v4 net-next 4/6] ila: create main ila source file Tom Herbert
@ 2017-12-15 18:27 ` Tom Herbert
2017-12-15 18:28 ` [PATCH v4 net-next 6/6] ila: Route notify Tom Herbert
5 siblings, 0 replies; 12+ messages in thread
From: Tom Herbert @ 2017-12-15 18:27 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
Add ILA_CMD_FLUSH netlink command to clear the ILA translation table.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/uapi/linux/ila.h | 1 +
net/ipv6/ila/ila.h | 1 +
net/ipv6/ila/ila_main.c | 6 +++++
net/ipv6/ila/ila_xlat.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
index 483b77af4eb8..db45d3e49a12 100644
--- a/include/uapi/linux/ila.h
+++ b/include/uapi/linux/ila.h
@@ -30,6 +30,7 @@ enum {
ILA_CMD_ADD,
ILA_CMD_DEL,
ILA_CMD_GET,
+ ILA_CMD_FLUSH,
__ILA_CMD_MAX,
};
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index faba7824ea56..1f747bcbec29 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -123,6 +123,7 @@ void ila_xlat_exit_net(struct net *net);
int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_dump_start(struct netlink_callback *cb);
int ila_xlat_nl_dump_done(struct netlink_callback *cb);
int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb);
diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c
index f6ac6b14577e..18fac76b9520 100644
--- a/net/ipv6/ila/ila_main.c
+++ b/net/ipv6/ila/ila_main.c
@@ -27,6 +27,12 @@ static const struct genl_ops ila_nl_ops[] = {
.flags = GENL_ADMIN_PERM,
},
{
+ .cmd = ILA_CMD_FLUSH,
+ .doit = ila_xlat_nl_cmd_flush,
+ .policy = ila_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
.cmd = ILA_CMD_GET,
.doit = ila_xlat_nl_cmd_get_mapping,
.start = ila_xlat_nl_dump_start,
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index d05de891dfb6..51a15ce50a64 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -164,9 +164,9 @@ static inline void ila_release(struct ila_map *ila)
kfree_rcu(ila, rcu);
}
-static void ila_free_cb(void *ptr, void *arg)
+static void ila_free_node(struct ila_map *ila)
{
- struct ila_map *ila = (struct ila_map *)ptr, *next;
+ struct ila_map *next;
/* Assume rcu_readlock held */
while (ila) {
@@ -176,6 +176,11 @@ static void ila_free_cb(void *ptr, void *arg)
}
}
+static void ila_free_cb(void *ptr, void *arg)
+{
+ ila_free_node((struct ila_map *)ptr);
+}
+
static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila);
static unsigned int
@@ -365,6 +370,59 @@ int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
return 0;
}
+static inline spinlock_t *lock_from_ila_map(struct ila_net *ilan,
+ struct ila_map *ila)
+{
+ return ila_get_lock(ilan, ila->xp.ip.locator_match);
+}
+
+int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct ila_net *ilan = net_generic(net, ila_net_id);
+ struct rhashtable_iter iter;
+ struct ila_map *ila;
+ spinlock_t *lock;
+ int ret;
+
+ ret = rhashtable_walk_init(&ilan->xlat.rhash_table, &iter, GFP_KERNEL);
+ if (ret)
+ goto done;
+
+ rhashtable_walk_start(&iter);
+
+ for (;;) {
+ ila = rhashtable_walk_next(&iter);
+
+ if (IS_ERR(ila)) {
+ if (PTR_ERR(ila) == -EAGAIN)
+ continue;
+ ret = PTR_ERR(ila);
+ goto done;
+ } else if (!ila) {
+ break;
+ }
+
+ lock = lock_from_ila_map(ilan, ila);
+
+ spin_lock(lock);
+
+ ret = rhashtable_remove_fast(&ilan->xlat.rhash_table,
+ &ila->node, rht_params);
+ if (!ret)
+ ila_free_node(ila);
+
+ spin_unlock(lock);
+
+ if (ret)
+ break;
+ }
+
+done:
+ rhashtable_walk_stop(&iter);
+ return ret;
+}
+
static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
{
if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 net-next 6/6] ila: Route notify
2017-12-15 18:27 [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes Tom Herbert
` (4 preceding siblings ...)
2017-12-15 18:27 ` [PATCH v4 net-next 5/6] ila: Flush netlink command to clear xlat table Tom Herbert
@ 2017-12-15 18:28 ` Tom Herbert
2017-12-16 22:18 ` [RFC PATCH] ila: ila_notify() can be static kbuild test robot
` (2 more replies)
5 siblings, 3 replies; 12+ messages in thread
From: Tom Herbert @ 2017-12-15 18:28 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
Implement RTM notifications for ILA routers. This adds support to
ILA LWT to send a netlink RTM message when a router is uses.
THe ILA notify mechanism can be used in two contexts:
- On an ILA forwarding cache a route prefix can be configured to
do an ILA notification. This method is used when address
resolution needs to be done on an address.
- One an ILA router an ILA host route entry may include a
noitification. The purpose of this is to get a notification
to a userspace daemon to send and ILA redirect
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/uapi/linux/ila.h | 2 +
include/uapi/linux/rtnetlink.h | 8 +-
net/ipv6/ila/ila_lwt.c | 268 ++++++++++++++++++++++++++++-------------
3 files changed, 193 insertions(+), 85 deletions(-)
diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
index db45d3e49a12..5675f3e71fac 100644
--- a/include/uapi/linux/ila.h
+++ b/include/uapi/linux/ila.h
@@ -19,6 +19,8 @@ enum {
ILA_ATTR_CSUM_MODE, /* u8 */
ILA_ATTR_IDENT_TYPE, /* u8 */
ILA_ATTR_HOOK_TYPE, /* u8 */
+ ILA_ATTR_NOTIFY_DST, /* flag */
+ ILA_ATTR_NOTIFY_SRC, /* flag */
__ILA_ATTR_MAX,
};
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index d8b5f80c2ea6..8d358a300d8a 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -13,7 +13,8 @@
*/
#define RTNL_FAMILY_IPMR 128
#define RTNL_FAMILY_IP6MR 129
-#define RTNL_FAMILY_MAX 129
+#define RTNL_FAMILY_ILA 130
+#define RTNL_FAMILY_MAX 130
/****
* Routing/neighbour discovery messages.
@@ -150,6 +151,9 @@ enum {
RTM_NEWCACHEREPORT = 96,
#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
+ RTM_ADDR_RESOLVE = 98,
+#define RTM_ADDR_RESOLVE RTM_ADDR_RESOLVE
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -676,6 +680,8 @@ enum rtnetlink_groups {
#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R
RTNLGRP_IPV6_MROUTE_R,
#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
+ RTNLGRP_ILA_NOTIFY,
+#define RTNLGRP_ILA_NOTIFY RTNLGRP_ILA_NOTIFY
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 9f1e46a1468e..303c91e3bf76 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -19,10 +19,15 @@
struct ila_lwt {
struct ila_params p;
struct dst_cache dst_cache;
+ u8 hook_type;
u32 connected : 1;
- u32 lwt_output : 1;
+ u32 xlat : 1;
+ u32 notify : 2;
};
+#define ILA_NOTIFY_DST 1
+#define ILA_NOTIFY_SRC 2
+
static inline struct ila_lwt *ila_lwt_lwtunnel(
struct lwtunnel_state *lwt)
{
@@ -35,6 +40,67 @@ static inline struct ila_params *ila_params_lwtunnel(
return &ila_lwt_lwtunnel(lwt)->p;
}
+static size_t ila_rslv_msgsize(void)
+{
+ size_t len =
+ NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(16) /* RTA_DST */
+ + nla_total_size(16) /* RTA_SRC */
+ ;
+
+ return len;
+}
+
+void ila_notify(struct net *net, struct sk_buff *skb, struct ila_lwt *lwt)
+{
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ int flags = NLM_F_MULTI;
+ struct sk_buff *nlskb;
+ struct nlmsghdr *nlh;
+ struct rtmsg *rtm;
+ int err = 0;
+
+ /* Send ILA notification to user */
+ nlskb = nlmsg_new(ila_rslv_msgsize(), GFP_KERNEL);
+ if (!nlskb)
+ return;
+
+ nlh = nlmsg_put(nlskb, 0, 0, RTM_ADDR_RESOLVE, sizeof(*rtm), flags);
+ if (!nlh) {
+ err = -EMSGSIZE;
+ goto errout;
+ }
+
+ rtm = nlmsg_data(nlh);
+ rtm->rtm_family = AF_INET6;
+ rtm->rtm_dst_len = 128;
+ rtm->rtm_src_len = 0;
+ rtm->rtm_tos = 0;
+ rtm->rtm_table = RT6_TABLE_UNSPEC;
+ rtm->rtm_type = RTN_UNICAST;
+ rtm->rtm_scope = RT_SCOPE_UNIVERSE;
+
+ if (((lwt->notify & ILA_NOTIFY_DST) &&
+ nla_put_in6_addr(nlskb, RTA_DST, &ip6h->daddr)) ||
+ ((lwt->notify & ILA_NOTIFY_SRC) &&
+ nla_put_in6_addr(nlskb, RTA_SRC, &ip6h->saddr))) {
+ nlmsg_cancel(nlskb, nlh);
+ err = -EMSGSIZE;
+ goto errout;
+ }
+
+ nlmsg_end(nlskb, nlh);
+
+ rtnl_notify(nlskb, net, 0, RTNLGRP_ILA_NOTIFY, NULL, GFP_ATOMIC);
+
+ return;
+
+errout:
+ kfree_skb(nlskb);
+ WARN_ON(err == -EMSGSIZE);
+ rtnl_set_sk_err(net, RTNLGRP_ILA_NOTIFY, err);
+}
+
static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct dst_entry *orig_dst = skb_dst(skb);
@@ -46,11 +112,14 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
if (skb->protocol != htons(ETH_P_IPV6))
goto drop;
- if (ilwt->lwt_output)
+ if (ilwt->xlat)
ila_update_ipv6_locator(skb,
ila_params_lwtunnel(orig_dst->lwtstate),
true);
+ if (ilwt->notify)
+ ila_notify(net, skb, ilwt);
+
if (rt->rt6i_flags & (RTF_GATEWAY | RTF_CACHE)) {
/* Already have a next hop address in route, no need for
* dest cache route.
@@ -106,11 +175,14 @@ static int ila_input(struct sk_buff *skb)
if (skb->protocol != htons(ETH_P_IPV6))
goto drop;
- if (!ilwt->lwt_output)
+ if (ilwt->xlat)
ila_update_ipv6_locator(skb,
ila_params_lwtunnel(dst->lwtstate),
false);
+ if (ilwt->notify)
+ ila_notify(dev_net(dst->dev), skb, ilwt);
+
return dst->lwtstate->orig_input(skb);
drop:
@@ -123,6 +195,8 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
[ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
[ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
[ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8, },
+ [ILA_ATTR_NOTIFY_DST] = { .type = NLA_FLAG },
+ [ILA_ATTR_NOTIFY_SRC] = { .type = NLA_FLAG },
};
static int ila_build_state(struct net *net, struct nlattr *nla,
@@ -130,64 +204,73 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{
- struct ila_lwt *ilwt;
- struct ila_params *p;
- struct nlattr *tb[ILA_ATTR_MAX + 1];
- struct lwtunnel_state *newts;
const struct fib6_config *cfg6 = cfg;
- struct ila_addr *iaddr;
+ struct ila_addr *iaddr = (struct ila_addr *)&cfg6->fc_dst;
u8 ident_type = ILA_ATYPE_USE_FORMAT;
u8 hook_type = ILA_HOOK_ROUTE_OUTPUT;
+ struct nlattr *tb[ILA_ATTR_MAX + 1];
u8 csum_mode = ILA_CSUM_NO_ACTION;
- bool lwt_output = true;
+ struct lwtunnel_state *newts;
+ struct ila_lwt *ilwt;
+ struct ila_params *p;
u8 eff_ident_type;
- int ret;
+ int err;
if (family != AF_INET6)
return -EINVAL;
- ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
- if (ret < 0)
- return ret;
+ err = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
+ if (err < 0)
+ return err;
- if (!tb[ILA_ATTR_LOCATOR])
- return -EINVAL;
+ if (tb[ILA_ATTR_LOCATOR]) {
+ /* Doing ILA translation */
- iaddr = (struct ila_addr *)&cfg6->fc_dst;
+ if (tb[ILA_ATTR_IDENT_TYPE])
+ ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]);
- if (tb[ILA_ATTR_IDENT_TYPE])
- ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]);
+ if (ident_type == ILA_ATYPE_USE_FORMAT) {
+ /* Infer identifier type from type field in formatted
+ * identifier.
+ */
- if (ident_type == ILA_ATYPE_USE_FORMAT) {
- /* Infer identifier type from type field in formatted
- * identifier.
- */
+ if (cfg6->fc_dst_len < 8 *
+ sizeof(struct ila_locator) + 3) {
+ /* Need to have full locator and at least type
+ * field included in destination
+ */
+ return -EINVAL;
+ }
+
+ eff_ident_type = iaddr->ident.type;
+ } else {
+ eff_ident_type = ident_type;
+ }
- if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
- /* Need to have full locator and at least type field
- * included in destination
- */
+ switch (eff_ident_type) {
+ case ILA_ATYPE_IID:
+ /* Don't allow ILA for IID type */
+ return -EINVAL;
+ case ILA_ATYPE_LUID:
+ break;
+ case ILA_ATYPE_VIRT_V4:
+ case ILA_ATYPE_VIRT_UNI_V6:
+ case ILA_ATYPE_VIRT_MULTI_V6:
+ case ILA_ATYPE_NONLOCAL_ADDR:
+ /* These ILA formats are not supported yet. */
+ default:
return -EINVAL;
}
- eff_ident_type = iaddr->ident.type;
- } else {
- eff_ident_type = ident_type;
- }
+ csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
- switch (eff_ident_type) {
- case ILA_ATYPE_IID:
- /* Don't allow ILA for IID type */
- return -EINVAL;
- case ILA_ATYPE_LUID:
- break;
- case ILA_ATYPE_VIRT_V4:
- case ILA_ATYPE_VIRT_UNI_V6:
- case ILA_ATYPE_VIRT_MULTI_V6:
- case ILA_ATYPE_NONLOCAL_ADDR:
- /* These ILA formats are not supported yet. */
- default:
- return -EINVAL;
+ if (csum_mode == ILA_CSUM_NEUTRAL_MAP &&
+ ila_csum_neutral_set(iaddr->ident)) {
+ /* Don't allow translation if checksum neutral bit is
+ * configured and it's set in the SIR address.
+ */
+ return -EINVAL;
+ }
}
if (tb[ILA_ATTR_HOOK_TYPE])
@@ -195,58 +278,62 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
switch (hook_type) {
case ILA_HOOK_ROUTE_OUTPUT:
- lwt_output = true;
- break;
case ILA_HOOK_ROUTE_INPUT:
- lwt_output = false;
break;
default:
return -EINVAL;
}
- if (tb[ILA_ATTR_CSUM_MODE])
- csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
-
- if (csum_mode == ILA_CSUM_NEUTRAL_MAP &&
- ila_csum_neutral_set(iaddr->ident)) {
- /* Don't allow translation if checksum neutral bit is
- * configured and it's set in the SIR address.
- */
- return -EINVAL;
- }
-
newts = lwtunnel_state_alloc(sizeof(*ilwt));
if (!newts)
return -ENOMEM;
ilwt = ila_lwt_lwtunnel(newts);
- ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
- if (ret) {
+
+ err = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
+ if (err) {
kfree(newts);
- return ret;
+ return err;
}
- ilwt->lwt_output = !!lwt_output;
+ newts->type = LWTUNNEL_ENCAP_ILA;
- p = ila_params_lwtunnel(newts);
+ switch (hook_type) {
+ case ILA_HOOK_ROUTE_OUTPUT:
+ newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT;
+ break;
+ case ILA_HOOK_ROUTE_INPUT:
+ newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
+ break;
+ }
- p->csum_mode = csum_mode;
- p->ident_type = ident_type;
- p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
+ ilwt->hook_type = hook_type;
- /* Precompute checksum difference for translation since we
- * know both the old locator and the new one.
- */
- p->locator_match = iaddr->loc;
+ if (tb[ILA_ATTR_NOTIFY_DST])
+ ilwt->notify |= ILA_NOTIFY_DST;
- ila_init_saved_csum(p);
+ if (tb[ILA_ATTR_NOTIFY_SRC])
+ ilwt->notify |= ILA_NOTIFY_SRC;
- newts->type = LWTUNNEL_ENCAP_ILA;
- newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
- LWTUNNEL_STATE_INPUT_REDIRECT;
+ p = ila_params_lwtunnel(newts);
- if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
- ilwt->connected = 1;
+ if (tb[ILA_ATTR_LOCATOR]) {
+ ilwt->xlat = true;
+ p->csum_mode = csum_mode;
+ p->ident_type = ident_type;
+ p->locator.v64 = (__force __be64)nla_get_u64(
+ tb[ILA_ATTR_LOCATOR]);
+
+ /* Precompute checksum difference for translation since we
+ * know both the old locator and the new one.
+ */
+ p->locator_match = iaddr->loc;
+
+ ila_init_saved_csum(p);
+
+ if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
+ ilwt->connected = 1;
+ }
*ts = newts;
@@ -264,21 +351,32 @@ static int ila_fill_encap_info(struct sk_buff *skb,
struct ila_params *p = ila_params_lwtunnel(lwtstate);
struct ila_lwt *ilwt = ila_lwt_lwtunnel(lwtstate);
- if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64,
- ILA_ATTR_PAD))
+ if (ilwt->xlat) {
+ if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR,
+ (__force u64)p->locator.v64,
+ ILA_ATTR_PAD))
goto nla_put_failure;
- if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE, (__force u8)p->csum_mode))
- goto nla_put_failure;
+ if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE,
+ (__force u8)p->csum_mode))
+ goto nla_put_failure;
- if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE, (__force u8)p->ident_type))
- goto nla_put_failure;
+ if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE,
+ (__force u8)p->ident_type))
+ goto nla_put_failure;
+ }
- if (nla_put_u8(skb, ILA_ATTR_HOOK_TYPE,
- ilwt->lwt_output ? ILA_HOOK_ROUTE_OUTPUT :
- ILA_HOOK_ROUTE_INPUT))
+ if (nla_put_u8(skb, ILA_ATTR_HOOK_TYPE, ilwt->hook_type))
goto nla_put_failure;
+ if (ilwt->notify & ILA_NOTIFY_DST)
+ if (nla_put_flag(skb, ILA_ATTR_NOTIFY_DST))
+ goto nla_put_failure;
+
+ if (ilwt->notify & ILA_NOTIFY_SRC)
+ if (nla_put_flag(skb, ILA_ATTR_NOTIFY_SRC))
+ goto nla_put_failure;
+
return 0;
nla_put_failure:
@@ -291,6 +389,8 @@ static int ila_encap_nlsize(struct lwtunnel_state *lwtstate)
nla_total_size(sizeof(u8)) + /* ILA_ATTR_CSUM_MODE */
nla_total_size(sizeof(u8)) + /* ILA_ATTR_IDENT_TYPE */
nla_total_size(sizeof(u8)) + /* ILA_ATTR_HOOK_TYPE */
+ nla_total_size(0) + /* ILA_ATTR_NOTIFY_DST */
+ nla_total_size(0) + /* ILA_ATTR_NOTIFY_SRC */
0;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v4 net-next 3/6] ila: Call library function alloc_bucket_locks
2017-12-15 18:27 ` [PATCH v4 net-next 3/6] ila: Call library function alloc_bucket_locks Tom Herbert
@ 2017-12-16 20:47 ` kbuild test robot
0 siblings, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2017-12-16 20:47 UTC (permalink / raw)
To: Tom Herbert; +Cc: kbuild-all, davem, netdev, roopa, rohit, Tom Herbert
[-- Attachment #1: Type: text/plain, Size: 1981 bytes --]
Hi Tom,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Tom-Herbert/net-ILA-notification-mechanism-and-fixes/20171217-041013
config: x86_64-randconfig-x019-201751 (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
Note: the linux-review/Tom-Herbert/net-ILA-notification-mechanism-and-fixes/20171217-041013 HEAD bdefe11e33bb3662a60476ea17663189974227a0 builds fine.
It only hurts bisectibility.
All error/warnings (new ones prefixed by >>):
net/ipv6/ila/ila_xlat.c: In function 'alloc_ila_locks':
>> net/ipv6/ila/ila_xlat.c:39:37: error: 'struct ila_net' has no member named 'xlat'
return alloc_bucket_spinlocks(&ilan->xlat.locks, &ilan->xlat.locks_mask,
^~
net/ipv6/ila/ila_xlat.c:39:56: error: 'struct ila_net' has no member named 'xlat'
return alloc_bucket_spinlocks(&ilan->xlat.locks, &ilan->xlat.locks_mask,
^~
net/ipv6/ila/ila_xlat.c: In function 'ila_exit_net':
net/ipv6/ila/ila_xlat.c:630:28: error: 'struct ila_net' has no member named 'xlat'
free_bucket_spinlocks(ilan->xlat.locks);
^~
net/ipv6/ila/ila_xlat.c: In function 'alloc_ila_locks':
>> net/ipv6/ila/ila_xlat.c:42:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
vim +39 net/ipv6/ila/ila_xlat.c
36
37 static int alloc_ila_locks(struct ila_net *ilan)
38 {
> 39 return alloc_bucket_spinlocks(&ilan->xlat.locks, &ilan->xlat.locks_mask,
40 MAX_LOCKS, LOCKS_PER_CPU,
41 GFP_KERNEL);
> 42 }
43
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31625 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH] ila: ila_notify() can be static
2017-12-15 18:28 ` [PATCH v4 net-next 6/6] ila: Route notify Tom Herbert
@ 2017-12-16 22:18 ` kbuild test robot
2017-12-16 22:18 ` [PATCH v4 net-next 6/6] ila: Route notify kbuild test robot
2017-12-19 16:28 ` Roopa Prabhu
2 siblings, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2017-12-16 22:18 UTC (permalink / raw)
To: Tom Herbert; +Cc: kbuild-all, davem, netdev, roopa, rohit, Tom Herbert
Fixes: bdefe11e33bb ("ila: Route notify")
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
---
ila_lwt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 303c91e..fbf6273 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -51,7 +51,7 @@ static size_t ila_rslv_msgsize(void)
return len;
}
-void ila_notify(struct net *net, struct sk_buff *skb, struct ila_lwt *lwt)
+static void ila_notify(struct net *net, struct sk_buff *skb, struct ila_lwt *lwt)
{
struct ipv6hdr *ip6h = ipv6_hdr(skb);
int flags = NLM_F_MULTI;
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v4 net-next 6/6] ila: Route notify
2017-12-15 18:28 ` [PATCH v4 net-next 6/6] ila: Route notify Tom Herbert
2017-12-16 22:18 ` [RFC PATCH] ila: ila_notify() can be static kbuild test robot
@ 2017-12-16 22:18 ` kbuild test robot
2017-12-19 16:28 ` Roopa Prabhu
2 siblings, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2017-12-16 22:18 UTC (permalink / raw)
To: Tom Herbert; +Cc: kbuild-all, davem, netdev, roopa, rohit, Tom Herbert
Hi Tom,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Tom-Herbert/net-ILA-notification-mechanism-and-fixes/20171217-041013
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 net-next 1/6] lwt: Add net to build_state argument
2017-12-15 18:27 ` [PATCH v4 net-next 1/6] lwt: Add net to build_state argument Tom Herbert
@ 2017-12-19 15:47 ` Roopa Prabhu
0 siblings, 0 replies; 12+ messages in thread
From: Roopa Prabhu @ 2017-12-19 15:47 UTC (permalink / raw)
To: Tom Herbert; +Cc: David Miller, netdev, rohit
On Fri, Dec 15, 2017 at 10:27 AM, Tom Herbert <tom@quantonium.net> wrote:
> Users of LWT need to know net if they want to have per net operations
> in LWT.
>
> Signed-off-by: Tom Herbert <tom@quantonium.net>
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 net-next 6/6] ila: Route notify
2017-12-15 18:28 ` [PATCH v4 net-next 6/6] ila: Route notify Tom Herbert
2017-12-16 22:18 ` [RFC PATCH] ila: ila_notify() can be static kbuild test robot
2017-12-16 22:18 ` [PATCH v4 net-next 6/6] ila: Route notify kbuild test robot
@ 2017-12-19 16:28 ` Roopa Prabhu
2 siblings, 0 replies; 12+ messages in thread
From: Roopa Prabhu @ 2017-12-19 16:28 UTC (permalink / raw)
To: Tom Herbert; +Cc: David Miller, netdev, rohit
On Fri, Dec 15, 2017 at 10:28 AM, Tom Herbert <tom@quantonium.net> wrote:
> Implement RTM notifications for ILA routers. This adds support to
> ILA LWT to send a netlink RTM message when a router is uses.
>
> THe ILA notify mechanism can be used in two contexts:
>
> - On an ILA forwarding cache a route prefix can be configured to
> do an ILA notification. This method is used when address
> resolution needs to be done on an address.
> - One an ILA router an ILA host route entry may include a
> noitification. The purpose of this is to get a notification
> to a userspace daemon to send and ILA redirect
>
> Signed-off-by: Tom Herbert <tom@quantonium.net>
> ---
> include/uapi/linux/ila.h | 2 +
> include/uapi/linux/rtnetlink.h | 8 +-
> net/ipv6/ila/ila_lwt.c | 268 ++++++++++++++++++++++++++++-------------
> 3 files changed, 193 insertions(+), 85 deletions(-)
>
> diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
> index db45d3e49a12..5675f3e71fac 100644
> --- a/include/uapi/linux/ila.h
> +++ b/include/uapi/linux/ila.h
> @@ -19,6 +19,8 @@ enum {
> ILA_ATTR_CSUM_MODE, /* u8 */
> ILA_ATTR_IDENT_TYPE, /* u8 */
> ILA_ATTR_HOOK_TYPE, /* u8 */
> + ILA_ATTR_NOTIFY_DST, /* flag */
> + ILA_ATTR_NOTIFY_SRC, /* flag */
>
> __ILA_ATTR_MAX,
> };
> diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
> index d8b5f80c2ea6..8d358a300d8a 100644
> --- a/include/uapi/linux/rtnetlink.h
> +++ b/include/uapi/linux/rtnetlink.h
> @@ -13,7 +13,8 @@
> */
> #define RTNL_FAMILY_IPMR 128
> #define RTNL_FAMILY_IP6MR 129
> -#define RTNL_FAMILY_MAX 129
> +#define RTNL_FAMILY_ILA 130
I don't see this being used, unless I missed it.
> +#define RTNL_FAMILY_MAX 130
>
> /****
> * Routing/neighbour discovery messages.
> @@ -150,6 +151,9 @@ enum {
> RTM_NEWCACHEREPORT = 96,
> #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
>
> + RTM_ADDR_RESOLVE = 98,
> +#define RTM_ADDR_RESOLVE RTM_ADDR_RESOLVE
Its nice that you are trying to add a generic resolver notify
format..., looks good...a few minor comments below for consistency:
your patch adds address resolve notifications with:
- generic notification msg type RTM_ADDR_RESOLVE with route msg format
- On the ILA specific RTNLGRP_ILA_NOTIFY multicast group
Other way to possibly format this for "generic" rtnl netlink resolver is:
- notification msg type RTM_NEWROUTE with route msg format (This is
for consistency: route msg format is always used with RTM_*ROUTE msg
types)
- route entry msg type RTNL_FAMILY_ILA (ie struct rtmsg-> rtm_family
to RTNL_FAMILY_ILA)
- generic address resolution netlink multicast group RTNLGRP_ADDR_RESOLVE_NOTIFY
OR keep everything "specific" to ILA using the ILA genl channel msg
format and family
Besides that, since you are using the route msg format, you could
potentially s/ADDR_RESOLVE/ROUTE_RESOLVE/g everywhere above.
> +
> __RTM_MAX,
> #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
> };
> @@ -676,6 +680,8 @@ enum rtnetlink_groups {
> #define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R
> RTNLGRP_IPV6_MROUTE_R,
> #define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
> + RTNLGRP_ILA_NOTIFY,
> +#define RTNLGRP_ILA_NOTIFY RTNLGRP_ILA_NOTIFY
> __RTNLGRP_MAX
> };
> #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
> diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
> index 9f1e46a1468e..303c91e3bf76 100644
> --- a/net/ipv6/ila/ila_lwt.c
> +++ b/net/ipv6/ila/ila_lwt.c
> @@ -19,10 +19,15 @@
> struct ila_lwt {
> struct ila_params p;
> struct dst_cache dst_cache;
> + u8 hook_type;
> u32 connected : 1;
> - u32 lwt_output : 1;
> + u32 xlat : 1;
> + u32 notify : 2;
> };
>
> +#define ILA_NOTIFY_DST 1
> +#define ILA_NOTIFY_SRC 2
> +
> static inline struct ila_lwt *ila_lwt_lwtunnel(
> struct lwtunnel_state *lwt)
> {
> @@ -35,6 +40,67 @@ static inline struct ila_params *ila_params_lwtunnel(
> return &ila_lwt_lwtunnel(lwt)->p;
> }
>
> +static size_t ila_rslv_msgsize(void)
> +{
> + size_t len =
> + NLMSG_ALIGN(sizeof(struct rtmsg))
> + + nla_total_size(16) /* RTA_DST */
> + + nla_total_size(16) /* RTA_SRC */
> + ;
> +
> + return len;
> +}
> +
> +void ila_notify(struct net *net, struct sk_buff *skb, struct ila_lwt *lwt)
> +{
> + struct ipv6hdr *ip6h = ipv6_hdr(skb);
> + int flags = NLM_F_MULTI;
> + struct sk_buff *nlskb;
> + struct nlmsghdr *nlh;
> + struct rtmsg *rtm;
> + int err = 0;
> +
> + /* Send ILA notification to user */
> + nlskb = nlmsg_new(ila_rslv_msgsize(), GFP_KERNEL);
> + if (!nlskb)
> + return;
> +
> + nlh = nlmsg_put(nlskb, 0, 0, RTM_ADDR_RESOLVE, sizeof(*rtm), flags);
> + if (!nlh) {
> + err = -EMSGSIZE;
> + goto errout;
> + }
> +
> + rtm = nlmsg_data(nlh);
> + rtm->rtm_family = AF_INET6;
> + rtm->rtm_dst_len = 128;
> + rtm->rtm_src_len = 0;
> + rtm->rtm_tos = 0;
> + rtm->rtm_table = RT6_TABLE_UNSPEC;
> + rtm->rtm_type = RTN_UNICAST;
> + rtm->rtm_scope = RT_SCOPE_UNIVERSE;
> +
> + if (((lwt->notify & ILA_NOTIFY_DST) &&
> + nla_put_in6_addr(nlskb, RTA_DST, &ip6h->daddr)) ||
> + ((lwt->notify & ILA_NOTIFY_SRC) &&
> + nla_put_in6_addr(nlskb, RTA_SRC, &ip6h->saddr))) {
> + nlmsg_cancel(nlskb, nlh);
> + err = -EMSGSIZE;
> + goto errout;
> + }
> +
> + nlmsg_end(nlskb, nlh);
> +
> + rtnl_notify(nlskb, net, 0, RTNLGRP_ILA_NOTIFY, NULL, GFP_ATOMIC);
> +
> + return;
> +
> +errout:
> + kfree_skb(nlskb);
> + WARN_ON(err == -EMSGSIZE);
> + rtnl_set_sk_err(net, RTNLGRP_ILA_NOTIFY, err);
> +}
> +
> static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
> {
> struct dst_entry *orig_dst = skb_dst(skb);
> @@ -46,11 +112,14 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
> if (skb->protocol != htons(ETH_P_IPV6))
> goto drop;
>
> - if (ilwt->lwt_output)
> + if (ilwt->xlat)
> ila_update_ipv6_locator(skb,
> ila_params_lwtunnel(orig_dst->lwtstate),
> true);
>
> + if (ilwt->notify)
> + ila_notify(net, skb, ilwt);
> +
> if (rt->rt6i_flags & (RTF_GATEWAY | RTF_CACHE)) {
> /* Already have a next hop address in route, no need for
> * dest cache route.
> @@ -106,11 +175,14 @@ static int ila_input(struct sk_buff *skb)
> if (skb->protocol != htons(ETH_P_IPV6))
> goto drop;
>
> - if (!ilwt->lwt_output)
> + if (ilwt->xlat)
> ila_update_ipv6_locator(skb,
> ila_params_lwtunnel(dst->lwtstate),
> false);
>
> + if (ilwt->notify)
> + ila_notify(dev_net(dst->dev), skb, ilwt);
> +
> return dst->lwtstate->orig_input(skb);
>
> drop:
> @@ -123,6 +195,8 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
> [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
> [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
> [ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8, },
> + [ILA_ATTR_NOTIFY_DST] = { .type = NLA_FLAG },
> + [ILA_ATTR_NOTIFY_SRC] = { .type = NLA_FLAG },
> };
>
> static int ila_build_state(struct net *net, struct nlattr *nla,
> @@ -130,64 +204,73 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
> struct lwtunnel_state **ts,
> struct netlink_ext_ack *extack)
> {
> - struct ila_lwt *ilwt;
> - struct ila_params *p;
> - struct nlattr *tb[ILA_ATTR_MAX + 1];
> - struct lwtunnel_state *newts;
> const struct fib6_config *cfg6 = cfg;
> - struct ila_addr *iaddr;
> + struct ila_addr *iaddr = (struct ila_addr *)&cfg6->fc_dst;
> u8 ident_type = ILA_ATYPE_USE_FORMAT;
> u8 hook_type = ILA_HOOK_ROUTE_OUTPUT;
> + struct nlattr *tb[ILA_ATTR_MAX + 1];
> u8 csum_mode = ILA_CSUM_NO_ACTION;
> - bool lwt_output = true;
> + struct lwtunnel_state *newts;
> + struct ila_lwt *ilwt;
> + struct ila_params *p;
> u8 eff_ident_type;
> - int ret;
> + int err;
>
> if (family != AF_INET6)
> return -EINVAL;
>
> - ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
> - if (ret < 0)
> - return ret;
> + err = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
> + if (err < 0)
> + return err;
>
> - if (!tb[ILA_ATTR_LOCATOR])
> - return -EINVAL;
> + if (tb[ILA_ATTR_LOCATOR]) {
> + /* Doing ILA translation */
>
> - iaddr = (struct ila_addr *)&cfg6->fc_dst;
> + if (tb[ILA_ATTR_IDENT_TYPE])
> + ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]);
>
> - if (tb[ILA_ATTR_IDENT_TYPE])
> - ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]);
> + if (ident_type == ILA_ATYPE_USE_FORMAT) {
> + /* Infer identifier type from type field in formatted
> + * identifier.
> + */
>
> - if (ident_type == ILA_ATYPE_USE_FORMAT) {
> - /* Infer identifier type from type field in formatted
> - * identifier.
> - */
> + if (cfg6->fc_dst_len < 8 *
> + sizeof(struct ila_locator) + 3) {
> + /* Need to have full locator and at least type
> + * field included in destination
> + */
> + return -EINVAL;
> + }
> +
> + eff_ident_type = iaddr->ident.type;
> + } else {
> + eff_ident_type = ident_type;
> + }
>
> - if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
> - /* Need to have full locator and at least type field
> - * included in destination
> - */
> + switch (eff_ident_type) {
> + case ILA_ATYPE_IID:
> + /* Don't allow ILA for IID type */
> + return -EINVAL;
> + case ILA_ATYPE_LUID:
> + break;
> + case ILA_ATYPE_VIRT_V4:
> + case ILA_ATYPE_VIRT_UNI_V6:
> + case ILA_ATYPE_VIRT_MULTI_V6:
> + case ILA_ATYPE_NONLOCAL_ADDR:
> + /* These ILA formats are not supported yet. */
> + default:
> return -EINVAL;
> }
>
> - eff_ident_type = iaddr->ident.type;
> - } else {
> - eff_ident_type = ident_type;
> - }
> + csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
>
> - switch (eff_ident_type) {
> - case ILA_ATYPE_IID:
> - /* Don't allow ILA for IID type */
> - return -EINVAL;
> - case ILA_ATYPE_LUID:
> - break;
> - case ILA_ATYPE_VIRT_V4:
> - case ILA_ATYPE_VIRT_UNI_V6:
> - case ILA_ATYPE_VIRT_MULTI_V6:
> - case ILA_ATYPE_NONLOCAL_ADDR:
> - /* These ILA formats are not supported yet. */
> - default:
> - return -EINVAL;
> + if (csum_mode == ILA_CSUM_NEUTRAL_MAP &&
> + ila_csum_neutral_set(iaddr->ident)) {
> + /* Don't allow translation if checksum neutral bit is
> + * configured and it's set in the SIR address.
> + */
> + return -EINVAL;
> + }
> }
>
> if (tb[ILA_ATTR_HOOK_TYPE])
> @@ -195,58 +278,62 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
>
> switch (hook_type) {
> case ILA_HOOK_ROUTE_OUTPUT:
> - lwt_output = true;
> - break;
> case ILA_HOOK_ROUTE_INPUT:
> - lwt_output = false;
> break;
> default:
> return -EINVAL;
> }
>
> - if (tb[ILA_ATTR_CSUM_MODE])
> - csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
> -
> - if (csum_mode == ILA_CSUM_NEUTRAL_MAP &&
> - ila_csum_neutral_set(iaddr->ident)) {
> - /* Don't allow translation if checksum neutral bit is
> - * configured and it's set in the SIR address.
> - */
> - return -EINVAL;
> - }
> -
> newts = lwtunnel_state_alloc(sizeof(*ilwt));
> if (!newts)
> return -ENOMEM;
>
> ilwt = ila_lwt_lwtunnel(newts);
> - ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
> - if (ret) {
> +
> + err = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
> + if (err) {
> kfree(newts);
> - return ret;
> + return err;
> }
>
> - ilwt->lwt_output = !!lwt_output;
> + newts->type = LWTUNNEL_ENCAP_ILA;
>
> - p = ila_params_lwtunnel(newts);
> + switch (hook_type) {
> + case ILA_HOOK_ROUTE_OUTPUT:
> + newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT;
> + break;
> + case ILA_HOOK_ROUTE_INPUT:
> + newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
> + break;
> + }
>
> - p->csum_mode = csum_mode;
> - p->ident_type = ident_type;
> - p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
> + ilwt->hook_type = hook_type;
>
> - /* Precompute checksum difference for translation since we
> - * know both the old locator and the new one.
> - */
> - p->locator_match = iaddr->loc;
> + if (tb[ILA_ATTR_NOTIFY_DST])
> + ilwt->notify |= ILA_NOTIFY_DST;
>
> - ila_init_saved_csum(p);
> + if (tb[ILA_ATTR_NOTIFY_SRC])
> + ilwt->notify |= ILA_NOTIFY_SRC;
>
> - newts->type = LWTUNNEL_ENCAP_ILA;
> - newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
> - LWTUNNEL_STATE_INPUT_REDIRECT;
> + p = ila_params_lwtunnel(newts);
>
> - if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
> - ilwt->connected = 1;
> + if (tb[ILA_ATTR_LOCATOR]) {
> + ilwt->xlat = true;
> + p->csum_mode = csum_mode;
> + p->ident_type = ident_type;
> + p->locator.v64 = (__force __be64)nla_get_u64(
> + tb[ILA_ATTR_LOCATOR]);
> +
> + /* Precompute checksum difference for translation since we
> + * know both the old locator and the new one.
> + */
> + p->locator_match = iaddr->loc;
> +
> + ila_init_saved_csum(p);
> +
> + if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
> + ilwt->connected = 1;
> + }
>
> *ts = newts;
>
> @@ -264,21 +351,32 @@ static int ila_fill_encap_info(struct sk_buff *skb,
> struct ila_params *p = ila_params_lwtunnel(lwtstate);
> struct ila_lwt *ilwt = ila_lwt_lwtunnel(lwtstate);
>
> - if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64,
> - ILA_ATTR_PAD))
> + if (ilwt->xlat) {
> + if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR,
> + (__force u64)p->locator.v64,
> + ILA_ATTR_PAD))
> goto nla_put_failure;
>
> - if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE, (__force u8)p->csum_mode))
> - goto nla_put_failure;
> + if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE,
> + (__force u8)p->csum_mode))
> + goto nla_put_failure;
>
> - if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE, (__force u8)p->ident_type))
> - goto nla_put_failure;
> + if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE,
> + (__force u8)p->ident_type))
> + goto nla_put_failure;
> + }
>
> - if (nla_put_u8(skb, ILA_ATTR_HOOK_TYPE,
> - ilwt->lwt_output ? ILA_HOOK_ROUTE_OUTPUT :
> - ILA_HOOK_ROUTE_INPUT))
> + if (nla_put_u8(skb, ILA_ATTR_HOOK_TYPE, ilwt->hook_type))
> goto nla_put_failure;
>
> + if (ilwt->notify & ILA_NOTIFY_DST)
> + if (nla_put_flag(skb, ILA_ATTR_NOTIFY_DST))
> + goto nla_put_failure;
> +
> + if (ilwt->notify & ILA_NOTIFY_SRC)
> + if (nla_put_flag(skb, ILA_ATTR_NOTIFY_SRC))
> + goto nla_put_failure;
> +
> return 0;
>
> nla_put_failure:
> @@ -291,6 +389,8 @@ static int ila_encap_nlsize(struct lwtunnel_state *lwtstate)
> nla_total_size(sizeof(u8)) + /* ILA_ATTR_CSUM_MODE */
> nla_total_size(sizeof(u8)) + /* ILA_ATTR_IDENT_TYPE */
> nla_total_size(sizeof(u8)) + /* ILA_ATTR_HOOK_TYPE */
> + nla_total_size(0) + /* ILA_ATTR_NOTIFY_DST */
> + nla_total_size(0) + /* ILA_ATTR_NOTIFY_SRC */
> 0;
> }
>
> --
> 2.11.0
>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2017-12-19 16:28 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-15 18:27 [PATCH v4 net-next 0/6] net: ILA notification mechanism and fixes Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 1/6] lwt: Add net to build_state argument Tom Herbert
2017-12-19 15:47 ` Roopa Prabhu
2017-12-15 18:27 ` [PATCH v4 net-next 2/6] ila: Fix use of rhashtable walk in ila_xlat.c Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 3/6] ila: Call library function alloc_bucket_locks Tom Herbert
2017-12-16 20:47 ` kbuild test robot
2017-12-15 18:27 ` [PATCH v4 net-next 4/6] ila: create main ila source file Tom Herbert
2017-12-15 18:27 ` [PATCH v4 net-next 5/6] ila: Flush netlink command to clear xlat table Tom Herbert
2017-12-15 18:28 ` [PATCH v4 net-next 6/6] ila: Route notify Tom Herbert
2017-12-16 22:18 ` [RFC PATCH] ila: ila_notify() can be static kbuild test robot
2017-12-16 22:18 ` [PATCH v4 net-next 6/6] ila: Route notify kbuild test robot
2017-12-19 16:28 ` Roopa Prabhu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.