All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver
@ 2017-12-11 20:38 Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 1/9] lwt: Add net to build_state argument Tom Herbert
                   ` (9 more replies)
  0 siblings, 10 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, roopa, rohit, Tom Herbert

This patch implements generic in-kernel network resolver. The idea is
that an LWT "resolver" route is set in the kernel to cover some prefix.
When a packet hits the route a netlink message is fired to request
resolution and pending resolutions are tracked in a table.

Route resolution works in the following manner:

Initial configuration:

0. An ila-rslv LWT route is set for some network prefix. The route
   includes an optional timeout to expire resolution.

Resolution process

1. Packet is sent to the a destination in the prefix being resolved
2. A lookup is performed on the destination address in a table of
   outstanding resolutions requests. If no entry is found:
    a. A new entry is created for the destination with a timeout
       value as set in the resolver route
    b. A netlink "RTM_ADDR_RESOLVE" message is sent to kick the
       resolution protocol or processing
3. The packet is forwarded per the resolver route

When an address is resolved

4. At some point a route is is set that resolves the outstanding
   request (for instance a host route is set for the destination).
   The entry is removed for the table. Subsequent packets to the
   destination will hit the new route rather than the resolver
   route since prefix is longer
5. Resolution entries may timeout and entry removed from the table.
   A subsequent packet to the destination will kick off a new
   resolution as in #2
6. The resolved route might also be timed out or removed, in which case
   subsequent packets to the same destination can trigger the
   resolution process

DOS mitigations:

- The number of outstanding resolutions is limited by the size of the
  table
- Timeout of pending entries limits the number of netlink resolution
  messages
- Packets are not queued that are pending resolution. In the current
  model that can be forwarded to a router that has all reachability
  information (ILA use case for example)

Possible future work

- An optional method to queue packets for pending resolution
- More DOS mitigations. It might make sense to limit the number of
resolutions per source address etc.

This patch set implements an ILA host side resolver. That uses the
generic resolver described above. This uses LWT to implement the hook
to a userspace resolver and tracks pending unresolved address using
the backend net resolver.

This patch set contains:

- A generic resolver backend infrastructure. This primary does two
  things: track unresolved addresses and implement a timeout for
  resolution not happening. These mechanisms provides rate limiting
  control over resolution requests (for instance in ILA it use used
  to rate limit requests to userspace to resolve addresses).
- The ILA resolver. This is implements to path from the kernel ILA
  implementation to a userspace daemon that an identifier address
  needs to be resolved.
- Routing messages are used over netlink to indicate resolution
  requests.
- Add net to ila build_state
- Add flush command to ila_xlat
- Fix uses for rhashtable for latest fixes

v3:
 - Removed rhashtable changes to their own patch set
 - Restructure ILA code to be more amenbale 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 (9):
  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
  net: Generic resolver backend
  ila: Resolver mechanism
  resolver: add netlink control
  ila: add netlink control ILA resolver

 include/net/lwtunnel.h         |   6 +-
 include/net/resolver.h         |  67 +++++
 include/uapi/linux/ila.h       |  21 ++
 include/uapi/linux/lwtunnel.h  |   1 +
 include/uapi/linux/rtnetlink.h |   8 +-
 net/Kconfig                    |   1 +
 net/Makefile                   |   1 +
 net/core/lwt_bpf.c             |   2 +-
 net/core/lwtunnel.c            |   6 +-
 net/ipv4/fib_semantics.c       |  13 +-
 net/ipv4/ip_tunnel_core.c      |   4 +-
 net/ipv6/Kconfig               |   1 +
 net/ipv6/ila/Makefile          |   2 +-
 net/ipv6/ila/ila.h             |  46 +++-
 net/ipv6/ila/ila_common.c      |  30 ---
 net/ipv6/ila/ila_lwt.c         |  10 +-
 net/ipv6/ila/ila_main.c        | 161 ++++++++++++
 net/ipv6/ila/ila_resolver.c    | 310 +++++++++++++++++++++++
 net/ipv6/ila/ila_xlat.c        | 280 ++++++++++-----------
 net/ipv6/route.c               |   2 +-
 net/ipv6/seg6_iptunnel.c       |   2 +-
 net/ipv6/seg6_local.c          |   5 +-
 net/mpls/mpls_iptunnel.c       |   2 +-
 net/resolver/Kconfig           |   7 +
 net/resolver/Makefile          |   8 +
 net/resolver/resolver.c        | 559 +++++++++++++++++++++++++++++++++++++++++
 26 files changed, 1356 insertions(+), 199 deletions(-)
 create mode 100644 include/net/resolver.h
 create mode 100644 net/ipv6/ila/ila_main.c
 create mode 100644 net/ipv6/ila/ila_resolver.c
 create mode 100644 net/resolver/Kconfig
 create mode 100644 net/resolver/Makefile
 create mode 100644 net/resolver/resolver.c

-- 
2.11.0

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v3 net-next 1/9] lwt: Add net to build_state argument
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 2/9] ila: Fix use of rhashtable walk in ila_xlat.c Tom Herbert
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 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] 17+ messages in thread

* [PATCH v3 net-next 2/9] ila: Fix use of rhashtable walk in ila_xlat.c
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 1/9] lwt: Add net to build_state argument Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 3/9] ila: Call library function alloc_bucket_locks Tom Herbert
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, roopa, rohit, Tom Herbert

Perform better EAGAIN handling, handle case where ila_dump_info
fails and we miss mis 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 | 60 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 44 insertions(+), 16 deletions(-)

diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 44c39c5f0638..9fca75b9cab3 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,37 +516,58 @@ 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 entty */
+	ila = rhashtable_walk_peek(rhiter);
 
+	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;
 		}
 
+		while (ila && skip) {
+			/* Skip over any ila entries in this list that we
+			 * have already dumped.
+			 */
+			ila = rcu_access_pointer(ila->next);
+			skip--;
+		}
 		while (ila) {
 			ret =  ila_dump_info(ila, NETLINK_CB(cb->skb).portid,
 					     cb->nlh->nlmsg_seq, NLM_F_MULTI,
 					     skb, ILA_CMD_GET);
 			if (ret)
-				goto done;
+				goto out;
 
 			ila = rcu_access_pointer(ila->next);
 		}
+		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] 17+ messages in thread

* [PATCH v3 net-next 3/9] ila: Call library function alloc_bucket_locks
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 1/9] lwt: Add net to build_state argument Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 2/9] ila: Fix use of rhashtable walk in ila_xlat.c Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 4/9] ila: create main ila source file Tom Herbert
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 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 9fca75b9cab3..402193ef74c2 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;
@@ -629,7 +617,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] 17+ messages in thread

* [PATCH v3 net-next 4/9] ila: create main ila source file
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
                   ` (2 preceding siblings ...)
  2017-12-11 20:38 ` [PATCH v3 net-next 3/9] ila: Call library function alloc_bucket_locks Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 5/9] ila: Flush netlink command to clear xlat table Tom Herbert
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, roopa, rohit, Tom Herbert

Create a main ila file that contains the module intialization 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 402193ef74c2..610852b3dfa7 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;
@@ -560,77 +541,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;
@@ -657,28 +596,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] 17+ messages in thread

* [PATCH v3 net-next 5/9] ila: Flush netlink command to clear xlat table
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
                   ` (3 preceding siblings ...)
  2017-12-11 20:38 ` [PATCH v3 net-next 4/9] ila: create main ila source file Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 6/9] net: Generic resolver backend Tom Herbert
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 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 610852b3dfa7..6bb1a081ff04 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] 17+ messages in thread

* [PATCH v3 net-next 6/9] net: Generic resolver backend
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
                   ` (4 preceding siblings ...)
  2017-12-11 20:38 ` [PATCH v3 net-next 5/9] ila: Flush netlink command to clear xlat table Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-14  7:16   ` kbuild test robot
  2017-12-11 20:38 ` [PATCH v3 net-next 7/9] ila: Resolver mechanism Tom Herbert
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, roopa, rohit, Tom Herbert

This patch implements the backend of a resolver, specifically it
provides a means to track unresolved addresses and expire entries
based on timeout.

The resolver is mostly a frontend to an rhashtable where the key
of the table is whatever address type or object is tracked. A resolver
instance is created by net_rslv_create. A resolver is destroyed by
net_rslv_destroy.

There are two functions that are used to manipulate entries in the
table: net_rslv_lookup_and_create and net_rslv_resolved.

net_rslv_lookup_and_create is called with an unresolved address as
the argument. It returns zero on success and an error on failure.
When called a lookup is performed to see if an entry for the address
is already in the table, if it is then the -EEXISTS is returned.  If
an entry is not found, one is created and zero is returned.  It is
expected that when an entry is new the address resolution protocol is
initiated (for instance a RTM_ADDR_RESOLVE message may be sent to a
userspace daemon as we will do in ILA). If net_rslv_lookup_and_create
returns an error other than -EEXIST then presumably the hash table
has reached the limit of number of outstanding unresolved addresses,
the caller should take appropriate actions to avoid spamming the
resolution protocol.

net_rslv_resolved is called when resolution is completely (e.g.
ILA locator mapping was instantiated for a locator. The entry is
removed for the hash table.

An argument to net_rslv_create indicates a time for the pending
resolution in milliseconds. If the timer fires before resolution
then the entry is removed from the table. Subsequently, another
attempt to resolve the same address will result in a new entry in
the table.

There is one callback functions that can be set as arugments in
net_rslv_create:

   - cmp_fn: Compare function for hash table. Arguments are the
       key and an object in the table. If this is NULL then the
       default memcmp of rhashtable is used.

DOS mitigation is done by limiting the number of entries in the
resolver table (the max_size which argument of net_rslv_create)
and setting a timeout. If the timeout is set then the maximum rate
of new resolution requests is max_table_size / timeout. For
instance, with a maximum size of 1000 entries and a timeout of 100
msecs the maximum rate of resolutions requests is 10000/s.

Signed-off-by: Tom Herbert <tom@quantonium.net>
---
 include/net/resolver.h  |  43 ++++++++
 net/Kconfig             |   1 +
 net/Makefile            |   1 +
 net/resolver/Kconfig    |   7 ++
 net/resolver/Makefile   |   8 ++
 net/resolver/resolver.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 343 insertions(+)
 create mode 100644 include/net/resolver.h
 create mode 100644 net/resolver/Kconfig
 create mode 100644 net/resolver/Makefile
 create mode 100644 net/resolver/resolver.c

diff --git a/include/net/resolver.h b/include/net/resolver.h
new file mode 100644
index 000000000000..f38c7e9f1205
--- /dev/null
+++ b/include/net/resolver.h
@@ -0,0 +1,43 @@
+/*
+ * Generic network address resovler backend
+ *
+ * Copyright (c) 2017 Tom Herbert <tom@quantonium.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __NET_RESOLVER_H
+#define __NET_RESOLVER_H
+
+#include <linux/rhashtable.h>
+#include <linux/types.h>
+
+struct net_rslv;
+
+typedef int (*net_rslv_cmpfn)(struct net_rslv *nrslv, const void *key,
+			      const void *object);
+
+struct net_rslv {
+	struct rhashtable rhash_table;
+	struct rhashtable_params params;
+	net_rslv_cmpfn rslv_cmp;
+	size_t obj_size;
+	spinlock_t *locks;
+	unsigned int locks_mask;
+	unsigned int hash_rnd;
+};
+
+struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len,
+				 size_t max_size, net_rslv_cmpfn cmp_fn);
+
+void net_rslv_destroy(struct net_rslv *nrslv);
+
+int net_rslv_lookup_and_create(struct net_rslv *nrslv, void *key,
+			       unsigned int timeout);
+
+void net_rslv_resolved(struct net_rslv *nrslv, void *key);
+
+#endif /* __NET_RESOLVER_H */
diff --git a/net/Kconfig b/net/Kconfig
index 9dba2715919d..b1e73325de6a 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -399,6 +399,7 @@ source "net/ceph/Kconfig"
 source "net/nfc/Kconfig"
 source "net/psample/Kconfig"
 source "net/ife/Kconfig"
+source "net/resolver/Kconfig"
 
 config LWTUNNEL
 	bool "Network light weight tunnels"
diff --git a/net/Makefile b/net/Makefile
index 14fede520840..6b3b0c5e676a 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -86,3 +86,4 @@ obj-y				+= l3mdev/
 endif
 obj-$(CONFIG_QRTR)		+= qrtr/
 obj-$(CONFIG_NET_NCSI)		+= ncsi/
+obj-$(CONFIG_NET_RESOLVER)	+= resolver/
diff --git a/net/resolver/Kconfig b/net/resolver/Kconfig
new file mode 100644
index 000000000000..99eff276e0b7
--- /dev/null
+++ b/net/resolver/Kconfig
@@ -0,0 +1,7 @@
+#
+# Net resolver configuration
+#
+
+menuconfig NET_RESOLVER
+        tristate
+	default n
diff --git a/net/resolver/Makefile b/net/resolver/Makefile
new file mode 100644
index 000000000000..fc15e6e5f19f
--- /dev/null
+++ b/net/resolver/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the generic network resolver
+#
+
+obj-$(CONFIG_NET_RESOLVER) += net_resolver.o
+
+net_resolver-objs := resolver.o
+
diff --git a/net/resolver/resolver.c b/net/resolver/resolver.c
new file mode 100644
index 000000000000..32a915ed8f93
--- /dev/null
+++ b/net/resolver/resolver.c
@@ -0,0 +1,283 @@
+/*
+ * net/core/resolver.c - Generic network address resolver backend
+ *
+ * Copyright (c) 2017 Tom Herbert <tom@quantonium.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <net/checksum.h>
+#include <net/ip.h>
+#include <net/ip6_fib.h>
+#include <net/lwtunnel.h>
+#include <net/protocol.h>
+#include <net/resolver.h>
+
+struct net_rslv_ent {
+	struct rhash_head node;
+	struct delayed_work timeout_work;
+	struct net_rslv *nrslv;
+
+	struct rcu_head rcu;
+
+	char object[];
+};
+
+static void net_rslv_destroy_rcu(struct rcu_head *head)
+{
+	struct net_rslv_ent *nrent = container_of(head, struct net_rslv_ent,
+						  rcu);
+	kfree(nrent);
+}
+
+static void net_rslv_destroy_entry(struct net_rslv *nrslv,
+				   struct net_rslv_ent *nrent)
+{
+	call_rcu(&nrent->rcu, net_rslv_destroy_rcu);
+}
+
+static inline spinlock_t *net_rslv_get_lock(struct net_rslv *nrslv, void *key)
+{
+	unsigned int hash;
+
+	/* Use the rhashtable hash function */
+	hash = rht_key_get_hash(&nrslv->rhash_table, key, nrslv->params,
+				nrslv->hash_rnd);
+
+	return &nrslv->locks[hash & nrslv->locks_mask];
+}
+
+static void net_rslv_delayed_work(struct work_struct *w)
+{
+	struct delayed_work *delayed_work = to_delayed_work(w);
+	struct net_rslv_ent *nrent = container_of(delayed_work,
+						  struct net_rslv_ent,
+						  timeout_work);
+	struct net_rslv *nrslv = nrent->nrslv;
+	spinlock_t *lock = net_rslv_get_lock(nrslv, nrent->object);
+
+	spin_lock(lock);
+	rhashtable_remove_fast(&nrslv->rhash_table, &nrent->node,
+			       nrslv->params);
+	spin_unlock(lock);
+
+	net_rslv_destroy_entry(nrslv, nrent);
+}
+
+static void net_rslv_ent_free_cb(void *ptr, void *arg)
+{
+	struct net_rslv_ent *nrent = (struct net_rslv_ent *)ptr;
+	struct net_rslv *nrslv = nrent->nrslv;
+
+	net_rslv_destroy_entry(nrslv, nrent);
+}
+
+void net_rslv_resolved(struct net_rslv *nrslv, void *key)
+{
+	spinlock_t *lock = net_rslv_get_lock(nrslv, key);
+	struct net_rslv_ent *nrent;
+
+	rcu_read_lock();
+
+	nrent = rhashtable_lookup_fast(&nrslv->rhash_table, key,
+				       nrslv->params);
+	if (!nrent)
+		goto out;
+
+	/* Cancel timer first */
+	cancel_delayed_work_sync(&nrent->timeout_work);
+
+	spin_lock(lock);
+
+	/* Lookup again just in case someone already removed */
+	nrent = rhashtable_lookup_fast(&nrslv->rhash_table, key,
+				       nrslv->params);
+	if (unlikely(!nrent)) {
+		spin_unlock(lock);
+		goto out;
+	}
+
+	rhashtable_remove_fast(&nrslv->rhash_table, &nrent->node,
+			       nrslv->params);
+	spin_unlock(lock);
+
+	net_rslv_destroy_entry(nrslv, nrent);
+
+out:
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(net_rslv_resolved);
+
+/* Called with hash bucket lock held */
+static int net_rslv_new_ent(struct net_rslv *nrslv, void *key,
+			    unsigned int timeout)
+{
+	struct net_rslv_ent *nrent;
+	int err;
+
+	nrent = kzalloc(sizeof(*nrent) + nrslv->obj_size, GFP_KERNEL);
+	if (!nrent)
+		return -ENOMEM;
+
+	/* Key is always at beginning of object data */
+	memcpy(nrent->object, key, nrslv->params.key_len);
+
+	nrent->nrslv = nrslv;
+
+	/* Put in hash table */
+	err = rhashtable_lookup_insert_fast(&nrslv->rhash_table,
+					    &nrent->node, nrslv->params);
+	if (err) {
+		kfree(nrent);
+		return err;
+	}
+
+	if (timeout) {
+		/* Schedule timeout for resolver */
+		INIT_DELAYED_WORK(&nrent->timeout_work, net_rslv_delayed_work);
+		schedule_delayed_work(&nrent->timeout_work,
+				      msecs_to_jiffies(timeout));
+	}
+
+	return 0;
+}
+
+int net_rslv_lookup_and_create(struct net_rslv *nrslv, void *key,
+			       unsigned int timeout)
+{
+	spinlock_t *lock = net_rslv_get_lock(nrslv, key);
+	int ret;
+
+	if (rhashtable_lookup_fast(&nrslv->rhash_table, key, nrslv->params))
+		return -EEXIST;
+
+	spin_lock(lock);
+
+	/* Check if someone beat us to the punch */
+	if (rhashtable_lookup_fast(&nrslv->rhash_table, key, nrslv->params)) {
+		spin_unlock(lock);
+		return -EEXIST;
+	}
+
+	ret = net_rslv_new_ent(nrslv, key, timeout);
+
+	spin_unlock(lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(net_rslv_lookup_and_create);
+
+static int net_rslv_cmp(struct rhashtable_compare_arg *arg,
+			const void *obj)
+{
+	struct net_rslv *nrslv = container_of(arg->ht, struct net_rslv,
+					      rhash_table);
+
+	return nrslv->rslv_cmp(nrslv, arg->key, obj);
+}
+
+#define LOCKS_PER_CPU	10
+#define MAX_LOCKS 1024
+
+struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len,
+				 size_t max_size,
+				 net_rslv_cmpfn cmp_fn)
+{
+	struct net_rslv *nrslv;
+	int err;
+
+	if (key_len < obj_size)
+		return ERR_PTR(-EINVAL);
+
+	nrslv = kzalloc(sizeof(*nrslv), GFP_KERNEL);
+	if (!nrslv)
+		return ERR_PTR(-ENOMEM);
+
+	err = alloc_bucket_spinlocks(&nrslv->locks, &nrslv->locks_mask,
+				     MAX_LOCKS, LOCKS_PER_CPU, GFP_KERNEL);
+	if (err)
+		return ERR_PTR(err);
+
+	nrslv->obj_size = obj_size;
+	nrslv->rslv_cmp = cmp_fn;
+	get_random_bytes(&nrslv->hash_rnd, sizeof(nrslv->hash_rnd));
+
+	nrslv->params.head_offset = offsetof(struct net_rslv_ent, node);
+	nrslv->params.key_offset = offsetof(struct net_rslv_ent, object);
+	nrslv->params.key_len = key_len;
+	nrslv->params.max_size = max_size;
+	nrslv->params.min_size = 256;
+	nrslv->params.automatic_shrinking = true;
+	nrslv->params.obj_cmpfn = cmp_fn ? net_rslv_cmp : NULL;
+
+	rhashtable_init(&nrslv->rhash_table, &nrslv->params);
+
+	return nrslv;
+}
+EXPORT_SYMBOL_GPL(net_rslv_create);
+
+static void net_rslv_cancel_all_delayed_work(struct net_rslv *nrslv)
+{
+	struct rhashtable_iter iter;
+	struct net_rslv_ent *nrent;
+	int ret;
+
+	ret = rhashtable_walk_init(&nrslv->rhash_table, &iter, GFP_ATOMIC);
+	if (WARN_ON(ret))
+		return;
+
+	rhashtable_walk_start(&iter);
+
+	for (;;) {
+		nrent = rhashtable_walk_next(&iter);
+
+		if (IS_ERR(nrent)) {
+			if (PTR_ERR(nrent) == -EAGAIN) {
+				/* New table, we're okay to continue */
+				continue;
+			}
+			ret = PTR_ERR(nrent);
+			break;
+		} else if (!nrent) {
+			break;
+		}
+
+		cancel_delayed_work_sync(&nrent->timeout_work);
+	}
+
+	rhashtable_walk_stop(&iter);
+	rhashtable_walk_exit(&iter);
+}
+
+void net_rslv_destroy(struct net_rslv *nrslv)
+{
+	/* First cancel delayed work in all the nodes. We don't want
+	 * delayed work trying to remove nodes from the table while
+	 * rhashtable_free_and_destroy is walking.
+	 */
+	net_rslv_cancel_all_delayed_work(nrslv);
+
+	rhashtable_free_and_destroy(&nrslv->rhash_table,
+				    net_rslv_ent_free_cb, NULL);
+
+	free_bucket_spinlocks(nrslv->locks);
+
+	kfree(nrslv);
+}
+EXPORT_SYMBOL_GPL(net_rslv_destroy);
+
+MODULE_AUTHOR("Tom Herbert <tom@quantonium.net>");
+MODULE_LICENSE("GPL");
+
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 net-next 7/9] ila: Resolver mechanism
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
                   ` (5 preceding siblings ...)
  2017-12-11 20:38 ` [PATCH v3 net-next 6/9] net: Generic resolver backend Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-14 11:00   ` [RFC PATCH] ila: ila_rslv_notify() can be static kbuild test robot
  2017-12-14 11:00   ` [PATCH v3 net-next 7/9] ila: Resolver mechanism kbuild test robot
  2017-12-11 20:38 ` [PATCH v3 net-next 8/9] resolver: add netlink control Tom Herbert
                   ` (2 subsequent siblings)
  9 siblings, 2 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, roopa, rohit, Tom Herbert

Implement an ILA resolver. This uses LWT to implement the hook to a
userspace resolver and tracks pending unresolved address using the
backend net resolver.

The idea is that the kernel sets an ILA resolver route to the
SIR prefix, something like:

ip route add 3333::/64 encap ila-resolve \
     via 2401:db00:20:911a::27:0 dev eth0

When a packet hits the route the address is looked up in a resolver
table. If the entry is created (no entry with the address already
exists) then an rtnl message is generated with group
RTNLGRP_ILA_NOTIFY and type RTM_ADDR_RESOLVE. A userspace
daemon can listen for such messages and perform an ILA resolution
protocol to determine the ILA mapping. If the mapping is resolved
then a /128 ila encap router is set so that host can perform
ILA translation and send directly to destination.

Signed-off-by: Tom Herbert <tom@quantonium.net>
---
 include/uapi/linux/ila.h       |   9 ++
 include/uapi/linux/lwtunnel.h  |   1 +
 include/uapi/linux/rtnetlink.h |   8 +-
 net/core/lwtunnel.c            |   2 +
 net/ipv6/Kconfig               |   1 +
 net/ipv6/ila/Makefile          |   2 +-
 net/ipv6/ila/ila.h             |  11 ++
 net/ipv6/ila/ila_lwt.c         |   8 ++
 net/ipv6/ila/ila_main.c        |  14 +++
 net/ipv6/ila/ila_resolver.c    | 244 +++++++++++++++++++++++++++++++++++++++++
 10 files changed, 298 insertions(+), 2 deletions(-)
 create mode 100644 net/ipv6/ila/ila_resolver.c

diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
index db45d3e49a12..66557265bf5b 100644
--- a/include/uapi/linux/ila.h
+++ b/include/uapi/linux/ila.h
@@ -65,4 +65,13 @@ enum {
 	ILA_HOOK_ROUTE_INPUT,
 };
 
+enum {
+	ILA_NOTIFY_ATTR_UNSPEC,
+	ILA_NOTIFY_ATTR_TIMEOUT,		/* u32 */
+
+	__ILA_NOTIFY_ATTR_MAX,
+};
+
+#define ILA_NOTIFY_ATTR_MAX	(__ILA_NOTIFY_ATTR_MAX - 1)
+
 #endif /* _UAPI_LINUX_ILA_H */
diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h
index de696ca12f2c..2eac16f8323f 100644
--- a/include/uapi/linux/lwtunnel.h
+++ b/include/uapi/linux/lwtunnel.h
@@ -13,6 +13,7 @@ enum lwtunnel_encap_types {
 	LWTUNNEL_ENCAP_SEG6,
 	LWTUNNEL_ENCAP_BPF,
 	LWTUNNEL_ENCAP_SEG6_LOCAL,
+	LWTUNNEL_ENCAP_ILA_NOTIFY,
 	__LWTUNNEL_ENCAP_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/core/lwtunnel.c b/net/core/lwtunnel.c
index b3f2f77dfe72..16b04d05e9b9 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -46,6 +46,8 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
 		return "BPF";
 	case LWTUNNEL_ENCAP_SEG6_LOCAL:
 		return "SEG6LOCAL";
+	case LWTUNNEL_ENCAP_ILA_NOTIFY:
+		return "ILA-NOTIFY";
 	case LWTUNNEL_ENCAP_IP6:
 	case LWTUNNEL_ENCAP_IP:
 	case LWTUNNEL_ENCAP_NONE:
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index ea71e4b0ab7a..5b0a6e1bd7cc 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -110,6 +110,7 @@ config IPV6_ILA
 	tristate "IPv6: Identifier Locator Addressing (ILA)"
 	depends on NETFILTER
 	select LWTUNNEL
+	select NET_RESOLVER
 	---help---
 	  Support for IPv6 Identifier Locator Addressing (ILA).
 
diff --git a/net/ipv6/ila/Makefile b/net/ipv6/ila/Makefile
index b7739aba6e68..3ec2d65ceee2 100644
--- a/net/ipv6/ila/Makefile
+++ b/net/ipv6/ila/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_IPV6_ILA) += ila.o
 
-ila-objs := ila_main.o ila_common.o ila_lwt.o ila_xlat.o
+ila-objs := ila_main.o ila_common.o ila_lwt.o ila_xlat.o ila_resolver.o
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index 1f747bcbec29..02a800c71796 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -15,6 +15,7 @@
 #include <linux/ip.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/rhashtable.h>
 #include <linux/socket.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
@@ -112,6 +113,9 @@ struct ila_net {
 		unsigned int locks_mask;
 		bool hooks_registered;
 	} xlat;
+	struct {
+		struct net_rslv *nrslv;
+	} rslv;
 };
 
 int ila_lwt_init(void);
@@ -120,6 +124,11 @@ void ila_lwt_fini(void);
 int ila_xlat_init_net(struct net *net);
 void ila_xlat_exit_net(struct net *net);
 
+int ila_rslv_init(void);
+void ila_rslv_fini(void);
+int ila_rslv_init_net(struct net *net);
+void ila_rslv_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);
@@ -132,4 +141,6 @@ extern unsigned int ila_net_id;
 
 extern struct genl_family ila_nl_family;
 
+void ila_rslv_resolved(struct ila_net *ilan, struct ila_addr *iaddr);
+
 #endif /* __ILA_H */
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 9f1e46a1468e..20dddc7ea8d0 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -12,6 +12,7 @@
 #include <net/ip6_fib.h>
 #include <net/ip6_route.h>
 #include <net/lwtunnel.h>
+#include <net/netns/generic.h>
 #include <net/protocol.h>
 #include <uapi/linux/ila.h>
 #include "ila.h"
@@ -250,6 +251,13 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
 
 	*ts = newts;
 
+	if (cfg6->fc_dst_len >= sizeof(struct ila_addr)) {
+		struct ila_net *ilan = net_generic(net, ila_net_id);
+
+		/* Cancel any pending resolution on this address */
+		ila_rslv_resolved(ilan, iaddr);
+	}
+
 	return 0;
 }
 
diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c
index 18fac76b9520..411d3d112157 100644
--- a/net/ipv6/ila/ila_main.c
+++ b/net/ipv6/ila/ila_main.c
@@ -64,14 +64,21 @@ static __net_init int ila_init_net(struct net *net)
 	if (err)
 		goto ila_xlat_init_fail;
 
+	err = ila_rslv_init_net(net);
+	if (err)
+		goto resolver_init_fail;
+
 	return 0;
 
 ila_xlat_init_fail:
+	ila_xlat_exit_net(net);
+resolver_init_fail:
 	return err;
 }
 
 static __net_exit void ila_exit_net(struct net *net)
 {
+	ila_rslv_exit_net(net);
 	ila_xlat_exit_net(net);
 }
 
@@ -98,8 +105,14 @@ static int __init ila_init(void)
 	if (ret)
 		goto fail_lwt;
 
+	ret = ila_rslv_init();
+	if (ret)
+		goto fail_rslv;
+
 	return 0;
 
+fail_rslv:
+	ila_lwt_fini();
 fail_lwt:
 	genl_unregister_family(&ila_nl_family);
 register_family_fail:
@@ -110,6 +123,7 @@ static int __init ila_init(void)
 
 static void __exit ila_fini(void)
 {
+	ila_rslv_fini();
 	ila_lwt_fini();
 	genl_unregister_family(&ila_nl_family);
 	unregister_pernet_device(&ila_net_ops);
diff --git a/net/ipv6/ila/ila_resolver.c b/net/ipv6/ila/ila_resolver.c
new file mode 100644
index 000000000000..8b9a3c5305a4
--- /dev/null
+++ b/net/ipv6/ila/ila_resolver.c
@@ -0,0 +1,244 @@
+/*
+ * net/core/ila_resolver.c - ILA address resolver
+ *
+ * Copyright (c) 2017 Tom Herbert <tom@quantonium.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <net/ip6_fib.h>
+#include <net/lwtunnel.h>
+#include <net/netns/generic.h>
+#include <net/resolver.h>
+#include <uapi/linux/ila.h>
+#include "ila.h"
+
+struct ila_notify_params {
+	unsigned int timeout;
+};
+
+static inline struct ila_notify_params *ila_notify_params_lwtunnel(
+	struct lwtunnel_state *lwstate)
+{
+	return (struct ila_notify_params *)lwstate->data;
+}
+
+static int ila_fill_notify(struct sk_buff *skb, struct in6_addr *addr,
+			   u32 pid, u32 seq, int event, int flags)
+{
+	struct nlmsghdr *nlh;
+	struct rtmsg *rtm;
+
+	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
+	if (!nlh)
+		return -EMSGSIZE;
+
+	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 (nla_put_in6_addr(skb, RTA_DST, addr)) {
+		nlmsg_cancel(skb, nlh);
+		return -EMSGSIZE;
+	}
+
+	nlmsg_end(skb, nlh);
+	return 0;
+}
+
+static size_t ila_rslv_msgsize(void)
+{
+	size_t len =
+		NLMSG_ALIGN(sizeof(struct rtmsg))
+		+ nla_total_size(16)     /* RTA_DST */
+		;
+
+	return len;
+}
+
+void ila_rslv_notify(struct net *net, struct sk_buff *skb)
+{
+	struct ipv6hdr *ip6h = ipv6_hdr(skb);
+	struct sk_buff *nlskb;
+	int err = 0;
+
+	/* Send ILA notification to user */
+	nlskb = nlmsg_new(ila_rslv_msgsize(), GFP_KERNEL);
+	if (!nlskb)
+		goto errout;
+
+	err = ila_fill_notify(nlskb, &ip6h->daddr, 0, 0, RTM_ADDR_RESOLVE,
+			      NLM_F_MULTI);
+	if (err < 0) {
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(nlskb);
+		goto errout;
+	}
+	rtnl_notify(nlskb, net, 0, RTNLGRP_ILA_NOTIFY, NULL, GFP_ATOMIC);
+	return;
+
+errout:
+	if (err < 0)
+		rtnl_set_sk_err(net, RTNLGRP_ILA_NOTIFY, err);
+}
+
+static int ila_rslv_output(struct net *net, struct sock *sk,
+			   struct sk_buff *skb)
+{
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+	struct dst_entry *dst = skb_dst(skb);
+	struct ipv6hdr *ip6h = ipv6_hdr(skb);
+	struct ila_notify_params *p;
+
+	p = ila_notify_params_lwtunnel(dst->lwtstate);
+
+	/* Net resolver create function returns zero only when a new
+	 * entry is create (returns -EEXIST is entry already in table)..
+	 */
+	if (!net_rslv_lookup_and_create(ilan->rslv.nrslv, &ip6h->daddr,
+					p->timeout))
+		ila_rslv_notify(net, skb);
+
+	return dst->lwtstate->orig_output(net, sk, skb);
+}
+
+void ila_rslv_resolved(struct ila_net *ilan, struct ila_addr *iaddr)
+{
+	if (ilan->rslv.nrslv)
+		net_rslv_resolved(ilan->rslv.nrslv, iaddr);
+}
+
+static int ila_rslv_input(struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb_dst(skb);
+
+	return dst->lwtstate->orig_input(skb);
+}
+
+static const struct nla_policy ila_notify_nl_policy[ILA_NOTIFY_ATTR_MAX + 1] = {
+	[ILA_NOTIFY_ATTR_TIMEOUT] = { .type = NLA_U32, },
+};
+
+static int ila_rslv_build_state(struct net *net, struct nlattr *nla,
+				unsigned int family, const void *cfg,
+				struct lwtunnel_state **ts,
+				struct netlink_ext_ack *extack)
+{
+	struct ila_notify_params *p;
+	struct nlattr *tb[ILA_NOTIFY_ATTR_MAX + 1];
+	struct lwtunnel_state *newts;
+	size_t encap_len = sizeof(*p);
+	int ret;
+
+	if (family != AF_INET6)
+		return -EINVAL;
+
+	ret = nla_parse_nested(tb, ILA_NOTIFY_ATTR_MAX, nla,
+			       ila_notify_nl_policy, extack);
+
+	if (ret < 0)
+		return ret;
+
+	newts = lwtunnel_state_alloc(encap_len);
+	if (!newts)
+		return -ENOMEM;
+
+	newts->type = LWTUNNEL_ENCAP_ILA_NOTIFY;
+	newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
+			LWTUNNEL_STATE_INPUT_REDIRECT;
+
+	p = ila_notify_params_lwtunnel(newts);
+
+	if (tb[ILA_NOTIFY_ATTR_TIMEOUT])
+		p->timeout = msecs_to_jiffies(nla_get_u32(
+			tb[ILA_NOTIFY_ATTR_TIMEOUT]));
+
+	*ts = newts;
+
+	return 0;
+}
+
+static int ila_rslv_fill_encap_info(struct sk_buff *skb,
+				    struct lwtunnel_state *lwtstate)
+{
+	struct ila_notify_params *p = ila_notify_params_lwtunnel(lwtstate);
+
+	if (nla_put_u32(skb, ILA_NOTIFY_ATTR_TIMEOUT,
+			(__force u32)jiffies_to_msecs(p->timeout)))
+		goto nla_put_failure;
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int ila_rslv_nlsize(struct lwtunnel_state *lwtstate)
+{
+	return nla_total_size(sizeof(u32)) + /* ILA_NOTIFY_ATTR_TIMEOUT */
+	       0;
+}
+
+static int ila_rslv_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
+{
+	return 0;
+}
+
+static const struct lwtunnel_encap_ops ila_rslv_ops = {
+	.build_state = ila_rslv_build_state,
+	.output = ila_rslv_output,
+	.input = ila_rslv_input,
+	.fill_encap = ila_rslv_fill_encap_info,
+	.get_encap_size = ila_rslv_nlsize,
+	.cmp_encap = ila_rslv_cmp,
+};
+
+#define ILA_MAX_SIZE 8192
+
+int ila_rslv_init_net(struct net *net)
+{
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+	struct net_rslv *nrslv;
+
+	nrslv = net_rslv_create(sizeof(struct ila_addr),
+				sizeof(struct ila_addr), ILA_MAX_SIZE, NULL);
+
+	if (IS_ERR(nrslv))
+		return PTR_ERR(nrslv);
+
+	ilan->rslv.nrslv = nrslv;
+
+	return 0;
+}
+
+void ila_rslv_exit_net(struct net *net)
+{
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+
+	if (ilan->rslv.nrslv)
+		net_rslv_destroy(ilan->rslv.nrslv);
+}
+
+int ila_rslv_init(void)
+{
+	return lwtunnel_encap_add_ops(&ila_rslv_ops, LWTUNNEL_ENCAP_ILA_NOTIFY);
+}
+
+void ila_rslv_fini(void)
+{
+	lwtunnel_encap_del_ops(&ila_rslv_ops, LWTUNNEL_ENCAP_ILA_NOTIFY);
+}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 net-next 8/9] resolver: add netlink control
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
                   ` (6 preceding siblings ...)
  2017-12-11 20:38 ` [PATCH v3 net-next 7/9] ila: Resolver mechanism Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-11 20:38 ` [PATCH v3 net-next 9/9] ila: add netlink control ILA resolver Tom Herbert
  2017-12-11 21:34 ` [PATCH v3 net-next 0/9] net: Generic network resolver backend and " David Miller
  9 siblings, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, roopa, rohit, Tom Herbert

Add interfaces into resolver backend that can be used to provide
netlink. The interface includes fucntions to support the common
netlink commands (get, add, list, delete, and flush). The
frontend that is using the resolver implements the actual
netlink interfaces for its service and calls the backend functions
to provide netlink for the resolver.

Signed-off-by: Tom Herbert <tom@quantonium.net>
---
 include/net/resolver.h      |  26 +++-
 net/ipv6/ila/ila_resolver.c |   3 +-
 net/resolver/resolver.c     | 280 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 305 insertions(+), 4 deletions(-)

diff --git a/include/net/resolver.h b/include/net/resolver.h
index f38c7e9f1205..307938ad91a6 100644
--- a/include/net/resolver.h
+++ b/include/net/resolver.h
@@ -14,12 +14,21 @@
 
 #include <linux/rhashtable.h>
 #include <linux/types.h>
+#include <net/genetlink.h>
+#include <uapi/linux/genetlink.h>
 
 struct net_rslv;
 
 typedef int (*net_rslv_cmpfn)(struct net_rslv *nrslv, const void *key,
 			      const void *object);
 
+struct net_rslv_netlink_map {
+	int dst_attr;
+	int timo_attr;
+	int get_cmd;
+	struct genl_family *genl_family;
+};
+
 struct net_rslv {
 	struct rhashtable rhash_table;
 	struct rhashtable_params params;
@@ -28,10 +37,12 @@ struct net_rslv {
 	spinlock_t *locks;
 	unsigned int locks_mask;
 	unsigned int hash_rnd;
+	const struct net_rslv_netlink_map *nlmap;
 };
 
 struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len,
-				 size_t max_size, net_rslv_cmpfn cmp_fn);
+				 size_t max_size, net_rslv_cmpfn cmp_fn,
+				 const struct net_rslv_netlink_map *nlmap);
 
 void net_rslv_destroy(struct net_rslv *nrslv);
 
@@ -40,4 +51,17 @@ int net_rslv_lookup_and_create(struct net_rslv *nrslv, void *key,
 
 void net_rslv_resolved(struct net_rslv *nrslv, void *key);
 
+int net_rslv_nl_cmd_add(struct net_rslv *nrslv, struct sk_buff *skb,
+			struct genl_info *info);
+int net_rslv_nl_cmd_del(struct net_rslv *nrslv, struct sk_buff *skb,
+			struct genl_info *info);
+int net_rslv_nl_cmd_get(struct net_rslv *nrslv, struct sk_buff *skb,
+			struct genl_info *info);
+int net_rslv_nl_cmd_flush(struct net_rslv *nrslv, struct sk_buff *skb,
+			  struct genl_info *info);
+int net_rslv_nl_dump_start(struct net_rslv *nrslv, struct netlink_callback *cb);
+int net_rslv_nl_dump_done(struct net_rslv *nrslv, struct netlink_callback *cb);
+int net_rslv_nl_dump(struct net_rslv *nrslv, struct sk_buff *skb,
+		     struct netlink_callback *cb);
+
 #endif /* __NET_RESOLVER_H */
diff --git a/net/ipv6/ila/ila_resolver.c b/net/ipv6/ila/ila_resolver.c
index 8b9a3c5305a4..2aebc0526221 100644
--- a/net/ipv6/ila/ila_resolver.c
+++ b/net/ipv6/ila/ila_resolver.c
@@ -215,7 +215,8 @@ int ila_rslv_init_net(struct net *net)
 	struct net_rslv *nrslv;
 
 	nrslv = net_rslv_create(sizeof(struct ila_addr),
-				sizeof(struct ila_addr), ILA_MAX_SIZE, NULL);
+				sizeof(struct ila_addr), ILA_MAX_SIZE, NULL,
+				NULL);
 
 	if (IS_ERR(nrslv))
 		return PTR_ERR(nrslv);
diff --git a/net/resolver/resolver.c b/net/resolver/resolver.c
index 32a915ed8f93..e2496b0bf852 100644
--- a/net/resolver/resolver.c
+++ b/net/resolver/resolver.c
@@ -19,11 +19,13 @@
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <net/checksum.h>
+#include <net/genetlink.h>
 #include <net/ip.h>
 #include <net/ip6_fib.h>
 #include <net/lwtunnel.h>
 #include <net/protocol.h>
 #include <net/resolver.h>
+#include <uapi/linux/genetlink.h>
 
 struct net_rslv_ent {
 	struct rhash_head node;
@@ -192,8 +194,8 @@ static int net_rslv_cmp(struct rhashtable_compare_arg *arg,
 #define MAX_LOCKS 1024
 
 struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len,
-				 size_t max_size,
-				 net_rslv_cmpfn cmp_fn)
+				 size_t max_size, net_rslv_cmpfn cmp_fn,
+				 const struct net_rslv_netlink_map *nlmap)
 {
 	struct net_rslv *nrslv;
 	int err;
@@ -212,6 +214,7 @@ struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len,
 
 	nrslv->obj_size = obj_size;
 	nrslv->rslv_cmp = cmp_fn;
+	nrslv->nlmap = nlmap;
 	get_random_bytes(&nrslv->hash_rnd, sizeof(nrslv->hash_rnd));
 
 	nrslv->params.head_offset = offsetof(struct net_rslv_ent, node);
@@ -278,6 +281,279 @@ void net_rslv_destroy(struct net_rslv *nrslv)
 }
 EXPORT_SYMBOL_GPL(net_rslv_destroy);
 
+/* Netlink access utility functions and structures. */
+
+struct net_rslv_params {
+	unsigned int timeout;
+	__u8 key[MAX_ADDR_LEN];
+	size_t keysize;
+};
+
+static int parse_nl_config(struct net_rslv *nrslv, struct genl_info *info,
+			   struct net_rslv_params *np)
+{
+	if (!info->attrs[nrslv->nlmap->dst_attr] ||
+	    nla_len(info->attrs[nrslv->nlmap->dst_attr]) !=
+					nrslv->params.key_len)
+		return -EINVAL;
+
+	memset(np, 0, sizeof(*np));
+
+	memcpy(np->key, nla_data(info->attrs[nrslv->nlmap->dst_attr]),
+	       nla_len(info->attrs[nrslv->nlmap->dst_attr]));
+
+	if (info->attrs[nrslv->nlmap->timo_attr])
+		np->timeout = nla_get_u32(info->attrs[nrslv->nlmap->timo_attr]);
+
+	return 0;
+}
+
+int net_rslv_nl_cmd_add(struct net_rslv *nrslv, struct sk_buff *skb,
+			struct genl_info *info)
+{
+	struct net_rslv_params p;
+	int err;
+
+	err = parse_nl_config(nrslv, info, &p);
+	if (err)
+		return err;
+
+	return net_rslv_lookup_and_create(nrslv, p.key, p.timeout);
+}
+EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_add);
+
+int net_rslv_nl_cmd_del(struct net_rslv *nrslv, struct sk_buff *skb,
+			struct genl_info *info)
+{
+	struct net_rslv_params p;
+	int err;
+
+	err = parse_nl_config(nrslv, info, &p);
+	if (err)
+		return err;
+
+	/* Treat removal as being resolved */
+	net_rslv_resolved(nrslv, p.key);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_del);
+
+static int net_rslv_fill_info(struct net_rslv *nrslv,
+			      struct net_rslv_ent *nrent,
+			      struct sk_buff *msg)
+{
+	int from_now = 0;
+
+	if (delayed_work_pending(&nrent->timeout_work)) {
+		unsigned long expires = nrent->timeout_work.timer.expires;
+
+		from_now = jiffies_to_msecs(expires - jiffies);
+
+		if (from_now < 0)
+			from_now = 0;
+	}
+
+	if (nla_put(msg, nrslv->nlmap->dst_attr, nrslv->params.key_len,
+		    nrent->object) ||
+	    nla_put_s32(msg, nrslv->nlmap->timo_attr, from_now))
+		return -1;
+
+	return 0;
+}
+
+static int net_rslv_dump_info(struct net_rslv *nrslv,
+			      struct net_rslv_ent *nrent, u32 portid, u32 seq,
+			      u32 flags, struct sk_buff *skb, u8 cmd)
+{
+	void *hdr;
+
+	hdr = genlmsg_put(skb, portid, seq, nrslv->nlmap->genl_family, flags,
+			  cmd);
+	if (!hdr)
+		return -ENOMEM;
+
+	if (net_rslv_fill_info(nrslv, nrent, skb) < 0)
+		goto nla_put_failure;
+
+	genlmsg_end(skb, hdr);
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(skb, hdr);
+	return -EMSGSIZE;
+}
+
+int net_rslv_nl_cmd_get(struct net_rslv *nrslv, struct sk_buff *skb,
+			struct genl_info *info)
+{
+	struct net_rslv_ent *nrent;
+	struct net_rslv_params p;
+	struct sk_buff *msg;
+	int err;
+
+	err = parse_nl_config(nrslv, info, &p);
+	if (err)
+		return err;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	rcu_read_lock();
+
+	nrent = rhashtable_lookup_fast(&nrslv->rhash_table, p.key,
+				       nrslv->params);
+	if (nrent)
+		err = net_rslv_dump_info(nrslv, nrent, info->snd_portid,
+					 info->snd_seq, 0, msg,
+					 info->genlhdr->cmd);
+
+	rcu_read_unlock();
+
+	if (err < 0)
+		goto out_free;
+
+	return genlmsg_reply(msg, info);
+
+out_free:
+	nlmsg_free(msg);
+	return err;
+}
+EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_get);
+
+int net_rslv_nl_cmd_flush(struct net_rslv *nrslv, struct sk_buff *skb,
+			  struct genl_info *info)
+{
+	struct rhashtable_iter iter;
+	struct net_rslv_ent *nrent;
+	spinlock_t *lock;
+	int ret;
+
+	ret = rhashtable_walk_init(&nrslv->rhash_table, &iter, GFP_KERNEL);
+	if (ret)
+		return ret;
+
+	rhashtable_walk_start(&iter);
+
+	for (;;) {
+		nrent = rhashtable_walk_next(&iter);
+
+		if (IS_ERR(nrent)) {
+			if (PTR_ERR(nrent) == -EAGAIN) {
+				/* New table, we're okay to continue */
+				continue;
+			}
+			ret = PTR_ERR(nrent);
+			break;
+		} else if (!nrent) {
+			break;
+		}
+
+		lock = net_rslv_get_lock(nrslv, nrent->object);
+
+		spin_lock(lock);
+		ret = rhashtable_remove_fast(&nrslv->rhash_table, &nrent->node,
+					     nrslv->params);
+		spin_unlock(lock);
+
+		if (ret)
+			break;
+	}
+
+	rhashtable_walk_stop(&iter);
+	rhashtable_walk_exit(&iter);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_flush);
+
+int net_rslv_nl_dump_start(struct net_rslv *nrslv, struct netlink_callback *cb)
+{
+	struct rhashtable_iter *iter;
+	int ret;
+
+	iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+	if (!iter)
+		return -ENOMEM;
+
+	ret = rhashtable_walk_init(&nrslv->rhash_table, iter, GFP_KERNEL);
+	if (ret) {
+		kfree(iter);
+		return ret;
+	}
+
+	cb->args[0] = (long)iter;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(net_rslv_nl_dump_start);
+
+int net_rslv_nl_dump_done(struct net_rslv *nrslv, struct netlink_callback *cb)
+{
+	struct rhashtable_iter *iter =
+				(struct rhashtable_iter *)cb->args[0];
+
+	rhashtable_walk_exit(iter);
+
+	kfree(iter);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(net_rslv_nl_dump_done);
+
+int net_rslv_nl_dump(struct net_rslv *nrslv, struct sk_buff *skb,
+		     struct netlink_callback *cb)
+{
+	struct rhashtable_iter *iter =
+				(struct rhashtable_iter *)cb->args[0];
+	struct net_rslv_ent *nrent;
+	int ret;
+
+	ret = rhashtable_walk_start_check(iter);
+	if (ret)
+		goto done;
+
+	/* Get first entty */
+	nrent = rhashtable_walk_peek(iter);
+
+	for (;;) {
+		if (IS_ERR(nrent)) {
+			ret = PTR_ERR(nrent);
+			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 done;
+			}
+			break;
+		} else if (!nrent) {
+			break;
+		}
+
+		ret =  net_rslv_dump_info(nrslv, nrent,
+					  NETLINK_CB(cb->skb).portid,
+					  cb->nlh->nlmsg_seq,
+					  NLM_F_MULTI, skb,
+					  nrslv->nlmap->get_cmd);
+		if (ret)
+			break;
+
+		/* Get next and advance the iter */
+		nrent = rhashtable_walk_next(iter);
+	}
+
+	ret = (skb->len ? : ret);
+
+done:
+	rhashtable_walk_stop(iter);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(net_rslv_nl_dump);
+
 MODULE_AUTHOR("Tom Herbert <tom@quantonium.net>");
 MODULE_LICENSE("GPL");
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 net-next 9/9] ila: add netlink control ILA resolver
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
                   ` (7 preceding siblings ...)
  2017-12-11 20:38 ` [PATCH v3 net-next 8/9] resolver: add netlink control Tom Herbert
@ 2017-12-11 20:38 ` Tom Herbert
  2017-12-11 21:34 ` [PATCH v3 net-next 0/9] net: Generic network resolver backend and " David Miller
  9 siblings, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 20:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, roopa, rohit, Tom Herbert

Add a netlink family to processe netlinkf for the ILA resolver.
This calls the net resolver netlink functions.

Signed-off-by: Tom Herbert <tom@quantonium.net>
---
 include/uapi/linux/ila.h    | 11 ++++++++
 net/ipv6/ila/ila.h          |  8 ++++++
 net/ipv6/ila/ila_main.c     | 26 ++++++++++++++++++
 net/ipv6/ila/ila_resolver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
index 66557265bf5b..2481dab25d57 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_RSLV_ATTR_DST,			/* IPv6 address */
+	ILA_RSLV_ATTR_TIMEOUT,			/* u32 */
 
 	__ILA_ATTR_MAX,
 };
@@ -31,6 +33,10 @@ enum {
 	ILA_CMD_DEL,
 	ILA_CMD_GET,
 	ILA_CMD_FLUSH,
+	ILA_RSLV_CMD_ADD,
+	ILA_RSLV_CMD_DEL,
+	ILA_RSLV_CMD_GET,
+	ILA_RSLV_CMD_FLUSH,
 
 	__ILA_CMD_MAX,
 };
@@ -68,10 +74,15 @@ enum {
 enum {
 	ILA_NOTIFY_ATTR_UNSPEC,
 	ILA_NOTIFY_ATTR_TIMEOUT,		/* u32 */
+	ILA_NOTIFY_ATTR_DST,			/* Binary address */
 
 	__ILA_NOTIFY_ATTR_MAX,
 };
 
 #define ILA_NOTIFY_ATTR_MAX	(__ILA_NOTIFY_ATTR_MAX - 1)
 
+/* NETLINK_GENERIC related info */
+#define ILA_RSLV_GENL_NAME	"ila-rslv"
+#define ILA_RSLV_GENL_VERSION	0x1
+
 #endif /* _UAPI_LINUX_ILA_H */
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index 02a800c71796..0aa99e359a38 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -137,6 +137,14 @@ 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);
 
+int ila_rslv_nl_cmd_add(struct sk_buff *skb, struct genl_info *info);
+int ila_rslv_nl_cmd_del(struct sk_buff *skb, struct genl_info *info);
+int ila_rslv_nl_cmd_get(struct sk_buff *skb, struct genl_info *info);
+int ila_rslv_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info);
+int ila_rslv_nl_dump_start(struct netlink_callback *cb);
+int ila_rslv_nl_dump_done(struct netlink_callback *cb);
+int ila_rslv_nl_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
 extern unsigned int ila_net_id;
 
 extern struct genl_family ila_nl_family;
diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c
index 411d3d112157..8589d422568b 100644
--- a/net/ipv6/ila/ila_main.c
+++ b/net/ipv6/ila/ila_main.c
@@ -40,6 +40,32 @@ static const struct genl_ops ila_nl_ops[] = {
 		.done = ila_xlat_nl_dump_done,
 		.policy = ila_nl_policy,
 	},
+	{
+		.cmd = ILA_RSLV_CMD_ADD,
+		.doit = ila_rslv_nl_cmd_add,
+		.policy = ila_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = ILA_RSLV_CMD_DEL,
+		.doit = ila_rslv_nl_cmd_del,
+		.policy = ila_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = ILA_RSLV_CMD_FLUSH,
+		.doit = ila_rslv_nl_cmd_flush,
+		.policy = ila_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = ILA_RSLV_CMD_GET,
+		.doit = ila_rslv_nl_cmd_get,
+		.start = ila_rslv_nl_dump_start,
+		.dumpit = ila_rslv_nl_dump,
+		.done = ila_rslv_nl_dump_done,
+		.policy = ila_nl_policy,
+	},
 };
 
 unsigned int ila_net_id;
diff --git a/net/ipv6/ila/ila_resolver.c b/net/ipv6/ila/ila_resolver.c
index 2aebc0526221..3278e93bb799 100644
--- a/net/ipv6/ila/ila_resolver.c
+++ b/net/ipv6/ila/ila_resolver.c
@@ -209,6 +209,13 @@ static const struct lwtunnel_encap_ops ila_rslv_ops = {
 
 #define ILA_MAX_SIZE 8192
 
+static struct net_rslv_netlink_map ila_netlink_map = {
+	.dst_attr = ILA_RSLV_ATTR_DST,
+	.timo_attr = ILA_RSLV_ATTR_TIMEOUT,
+	.get_cmd = ILA_RSLV_CMD_GET,
+	.genl_family = &ila_nl_family,
+};
+
 int ila_rslv_init_net(struct net *net)
 {
 	struct ila_net *ilan = net_generic(net, ila_net_id);
@@ -216,7 +223,7 @@ int ila_rslv_init_net(struct net *net)
 
 	nrslv = net_rslv_create(sizeof(struct ila_addr),
 				sizeof(struct ila_addr), ILA_MAX_SIZE, NULL,
-				NULL);
+				&ila_netlink_map);
 
 	if (IS_ERR(nrslv))
 		return PTR_ERR(nrslv);
@@ -234,6 +241,64 @@ void ila_rslv_exit_net(struct net *net)
 		net_rslv_destroy(ilan->rslv.nrslv);
 }
 
+/* Netlink access */
+
+int ila_rslv_nl_cmd_add(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net *net = sock_net(skb->sk);
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+
+	return net_rslv_nl_cmd_add(ilan->rslv.nrslv, skb, info);
+}
+
+int ila_rslv_nl_cmd_del(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net *net = sock_net(skb->sk);
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+
+	return net_rslv_nl_cmd_del(ilan->rslv.nrslv, skb, info);
+}
+
+int ila_rslv_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net *net = sock_net(skb->sk);
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+
+	return net_rslv_nl_cmd_get(ilan->rslv.nrslv, skb, info);
+}
+
+int ila_rslv_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net *net = sock_net(skb->sk);
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+
+	return net_rslv_nl_cmd_flush(ilan->rslv.nrslv, skb, info);
+}
+
+int ila_rslv_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);
+
+	return net_rslv_nl_dump_start(ilan->rslv.nrslv, cb);
+}
+
+int ila_rslv_nl_dump_done(struct netlink_callback *cb)
+{
+	struct net *net = sock_net(cb->skb->sk);
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+
+	return net_rslv_nl_dump_done(ilan->rslv.nrslv, cb);
+}
+
+int ila_rslv_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(cb->skb->sk);
+	struct ila_net *ilan = net_generic(net, ila_net_id);
+
+	return net_rslv_nl_dump(ilan->rslv.nrslv, skb, cb);
+}
+
 int ila_rslv_init(void)
 {
 	return lwtunnel_encap_add_ops(&ila_rslv_ops, LWTUNNEL_ENCAP_ILA_NOTIFY);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver
  2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
                   ` (8 preceding siblings ...)
  2017-12-11 20:38 ` [PATCH v3 net-next 9/9] ila: add netlink control ILA resolver Tom Herbert
@ 2017-12-11 21:34 ` David Miller
  2017-12-11 22:16   ` Tom Herbert
  9 siblings, 1 reply; 17+ messages in thread
From: David Miller @ 2017-12-11 21:34 UTC (permalink / raw)
  To: tom; +Cc: netdev, roopa, rohit

From: Tom Herbert <tom@quantonium.net>
Date: Mon, 11 Dec 2017 12:38:28 -0800

> DOS mitigations:
> 
> - The number of outstanding resolutions is limited by the size of the
>   table
> - Timeout of pending entries limits the number of netlink resolution
>   messages
> - Packets are not queued that are pending resolution. In the current
>   model that can be forwarded to a router that has all reachability
>   information (ILA use case for example)

None of these mitigation schemes matter.

If packet traffic can influence the table of entries (your cache
or whatever), then you will be DoS'able.

If you limit outstanding resolutions, you harm legitimate traffic
whose resolutions will not be processed now too just as equally
as you will harm "bad guy" traffic.

If you forward in the case of pending resolution, the bad guy can
make you forward everything there.  The bad guy can effectively
make your caching node stop caching completely.

Please, learn from OVS, the ipv4 routing cache, and the IPSEC
flow cache.  This kind of architecture, _especially_ when the
resolution is user side, is deeply flawed.

We're trying to remove code that does this kind of stuff, rather
than add new instances.

Thank you.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver
  2017-12-11 21:34 ` [PATCH v3 net-next 0/9] net: Generic network resolver backend and " David Miller
@ 2017-12-11 22:16   ` Tom Herbert
  2017-12-11 22:32     ` Tom Herbert
  2017-12-12  2:16     ` David Miller
  0 siblings, 2 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 22:16 UTC (permalink / raw)
  To: David Miller
  Cc: Linux Kernel Network Developers, Roopa Prabhu, Rohit LastName

On Mon, Dec 11, 2017 at 1:34 PM, David Miller <davem@davemloft.net> wrote:
> From: Tom Herbert <tom@quantonium.net>
> Date: Mon, 11 Dec 2017 12:38:28 -0800
>
>> DOS mitigations:
>>
>> - The number of outstanding resolutions is limited by the size of the
>>   table
>> - Timeout of pending entries limits the number of netlink resolution
>>   messages
>> - Packets are not queued that are pending resolution. In the current
>>   model that can be forwarded to a router that has all reachability
>>   information (ILA use case for example)
>
> None of these mitigation schemes matter.
>
> If packet traffic can influence the table of entries (your cache
> or whatever), then you will be DoS'able.
>
> If you limit outstanding resolutions, you harm legitimate traffic
> whose resolutions will not be processed now too just as equally
> as you will harm "bad guy" traffic.
>
David,

How can we build a system that allows an unlimited number of
resolutions without drop? Unless the resolution path can handle a
higher packet load than the receive path, there will be some place in
the system where memory is allocated and that limits the amount of
pending resolutions (i.e. pending packet skbs, entry in a resolution
table, skbs on a netlink socket).

> If you forward in the case of pending resolution, the bad guy can
> make you forward everything there.  The bad guy can effectively
> make your caching node stop caching completely.
>
But a DOS attack doesn't stop fowarding, at best it forces suboptimal
forwarding. This analogous to when the SYN cache is filled up but SYN
cookies allow forward progress in a degraded operational mode.

Thanks,
Tom

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver
  2017-12-11 22:16   ` Tom Herbert
@ 2017-12-11 22:32     ` Tom Herbert
  2017-12-12  2:16     ` David Miller
  1 sibling, 0 replies; 17+ messages in thread
From: Tom Herbert @ 2017-12-11 22:32 UTC (permalink / raw)
  To: Tom Herbert
  Cc: David Miller, Linux Kernel Network Developers, Roopa Prabhu,
	Rohit LastName

On Mon, Dec 11, 2017 at 2:16 PM, Tom Herbert <tom@quantonium.net> wrote:
> On Mon, Dec 11, 2017 at 1:34 PM, David Miller <davem@davemloft.net> wrote:
>> From: Tom Herbert <tom@quantonium.net>
>> Date: Mon, 11 Dec 2017 12:38:28 -0800
>>
>>> DOS mitigations:
>>>
>>> - The number of outstanding resolutions is limited by the size of the
>>>   table
>>> - Timeout of pending entries limits the number of netlink resolution
>>>   messages
>>> - Packets are not queued that are pending resolution. In the current
>>>   model that can be forwarded to a router that has all reachability
>>>   information (ILA use case for example)
>>
>> None of these mitigation schemes matter.
>>
>> If packet traffic can influence the table of entries (your cache
>> or whatever), then you will be DoS'able.
>>
>> If you limit outstanding resolutions, you harm legitimate traffic
>> whose resolutions will not be processed now too just as equally
>> as you will harm "bad guy" traffic.
>>
> David,
>
Actually, please disregard. I will respin to use secure redirects.

> How can we build a system that allows an unlimited number of
> resolutions without drop? Unless the resolution path can handle a
> higher packet load than the receive path, there will be some place in
> the system where memory is allocated and that limits the amount of
> pending resolutions (i.e. pending packet skbs, entry in a resolution
> table, skbs on a netlink socket).
>
>> If you forward in the case of pending resolution, the bad guy can
>> make you forward everything there.  The bad guy can effectively
>> make your caching node stop caching completely.
>>
> But a DOS attack doesn't stop fowarding, at best it forces suboptimal
> forwarding. This analogous to when the SYN cache is filled up but SYN
> cookies allow forward progress in a degraded operational mode.
>
> Thanks,
> Tom

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver
  2017-12-11 22:16   ` Tom Herbert
  2017-12-11 22:32     ` Tom Herbert
@ 2017-12-12  2:16     ` David Miller
  1 sibling, 0 replies; 17+ messages in thread
From: David Miller @ 2017-12-12  2:16 UTC (permalink / raw)
  To: tom; +Cc: netdev, roopa, rohit

From: Tom Herbert <tom@quantonium.net>
Date: Mon, 11 Dec 2017 14:16:17 -0800

> How can we build a system that allows an unlimited number of
> resolutions without drop?

IPV4 routing solves this with a prefixed trie, for example.

The fundamental backing datastructure for the switching
or whatever operation must be in-memory, in the kernel,
scalable, and without a fronting "cache".

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 net-next 6/9] net: Generic resolver backend
  2017-12-11 20:38 ` [PATCH v3 net-next 6/9] net: Generic resolver backend Tom Herbert
@ 2017-12-14  7:16   ` kbuild test robot
  0 siblings, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-12-14  7:16 UTC (permalink / raw)
  To: Tom Herbert; +Cc: kbuild-all, davem, netdev, roopa, rohit, Tom Herbert

[-- Attachment #1: Type: text/plain, Size: 1731 bytes --]

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-Generic-network-resolver-backend-and-ILA-resolver/20171214-142440
config: i386-randconfig-x016-201750 (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=i386 

All warnings (new ones prefixed by >>):

>> net/Kconfig:404: warning: menuconfig statement without prompt

vim +404 net/Kconfig

3908c690 Sjur Braendeland 2010-03-30  403  
499a2425 Roopa Prabhu     2015-07-21 @404  config LWTUNNEL
499a2425 Roopa Prabhu     2015-07-21  405  	bool "Network light weight tunnels"
499a2425 Roopa Prabhu     2015-07-21  406  	---help---
499a2425 Roopa Prabhu     2015-07-21  407  	  This feature provides an infrastructure to support light weight
499a2425 Roopa Prabhu     2015-07-21  408  	  tunnels like mpls. There is no netdevice associated with a light
499a2425 Roopa Prabhu     2015-07-21  409  	  weight tunnel endpoint. Tunnel encapsulation parameters are stored
499a2425 Roopa Prabhu     2015-07-21  410  	  with light weight tunnel state associated with fib routes.
cf4328cd Ivo van Doorn    2007-05-07  411  

:::::: The code at line 404 was first introduced by commit
:::::: 499a24256862714539e902c0499b67da2bb3ab72 lwtunnel: infrastructure for handling light weight tunnels like mpls

:::::: TO: Roopa Prabhu <roopa@cumulusnetworks.com>
:::::: CC: David S. Miller <davem@davemloft.net>

---
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: 24002 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [RFC PATCH] ila: ila_rslv_notify() can be static
  2017-12-11 20:38 ` [PATCH v3 net-next 7/9] ila: Resolver mechanism Tom Herbert
@ 2017-12-14 11:00   ` kbuild test robot
  2017-12-14 11:00   ` [PATCH v3 net-next 7/9] ila: Resolver mechanism kbuild test robot
  1 sibling, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-12-14 11:00 UTC (permalink / raw)
  To: Tom Herbert; +Cc: kbuild-all, davem, netdev, roopa, rohit, Tom Herbert


Fixes: af8ddae5aff5 ("ila: Resolver mechanism")
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
---
 ila_resolver.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/ila/ila_resolver.c b/net/ipv6/ila/ila_resolver.c
index 8b9a3c5..944981e 100644
--- a/net/ipv6/ila/ila_resolver.c
+++ b/net/ipv6/ila/ila_resolver.c
@@ -70,7 +70,7 @@ static size_t ila_rslv_msgsize(void)
 	return len;
 }
 
-void ila_rslv_notify(struct net *net, struct sk_buff *skb)
+static void ila_rslv_notify(struct net *net, struct sk_buff *skb)
 {
 	struct ipv6hdr *ip6h = ipv6_hdr(skb);
 	struct sk_buff *nlskb;

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 net-next 7/9] ila: Resolver mechanism
  2017-12-11 20:38 ` [PATCH v3 net-next 7/9] ila: Resolver mechanism Tom Herbert
  2017-12-14 11:00   ` [RFC PATCH] ila: ila_rslv_notify() can be static kbuild test robot
@ 2017-12-14 11:00   ` kbuild test robot
  1 sibling, 0 replies; 17+ messages in thread
From: kbuild test robot @ 2017-12-14 11:00 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-Generic-network-resolver-backend-and-ILA-resolver/20171214-142440
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] 17+ messages in thread

end of thread, other threads:[~2017-12-14 11:01 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-11 20:38 [PATCH v3 net-next 0/9] net: Generic network resolver backend and ILA resolver Tom Herbert
2017-12-11 20:38 ` [PATCH v3 net-next 1/9] lwt: Add net to build_state argument Tom Herbert
2017-12-11 20:38 ` [PATCH v3 net-next 2/9] ila: Fix use of rhashtable walk in ila_xlat.c Tom Herbert
2017-12-11 20:38 ` [PATCH v3 net-next 3/9] ila: Call library function alloc_bucket_locks Tom Herbert
2017-12-11 20:38 ` [PATCH v3 net-next 4/9] ila: create main ila source file Tom Herbert
2017-12-11 20:38 ` [PATCH v3 net-next 5/9] ila: Flush netlink command to clear xlat table Tom Herbert
2017-12-11 20:38 ` [PATCH v3 net-next 6/9] net: Generic resolver backend Tom Herbert
2017-12-14  7:16   ` kbuild test robot
2017-12-11 20:38 ` [PATCH v3 net-next 7/9] ila: Resolver mechanism Tom Herbert
2017-12-14 11:00   ` [RFC PATCH] ila: ila_rslv_notify() can be static kbuild test robot
2017-12-14 11:00   ` [PATCH v3 net-next 7/9] ila: Resolver mechanism kbuild test robot
2017-12-11 20:38 ` [PATCH v3 net-next 8/9] resolver: add netlink control Tom Herbert
2017-12-11 20:38 ` [PATCH v3 net-next 9/9] ila: add netlink control ILA resolver Tom Herbert
2017-12-11 21:34 ` [PATCH v3 net-next 0/9] net: Generic network resolver backend and " David Miller
2017-12-11 22:16   ` Tom Herbert
2017-12-11 22:32     ` Tom Herbert
2017-12-12  2:16     ` David Miller

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.