Netdev List
 help / color / mirror / Atom feed
From: Yevhen Orlov <yevhen.orlov@plvision.eu>
To: netdev@vger.kernel.org
Cc: Volodymyr Mytnyk <volodymyr.mytnyk@plvision.eu>,
	Taras Chornyi <taras.chornyi@plvision.eu>,
	Mickey Rachamim <mickeyr@marvell.com>,
	Serhiy Pshyk <serhiy.pshyk@plvision.eu>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Andrew Lunn <andrew@lunn.ch>,
	Stephen Hemminger <stephen@networkplumber.org>,
	linux-kernel@vger.kernel.org
Subject: [PATCH net-next v1 2/2] net: marvell: prestera: Handle ipv6 lpm/neigh events
Date: Mon, 19 Dec 2022 00:16:18 +0200	[thread overview]
Message-ID: <Y5+RMvhZCyG0bFgh@yorlov.ow.s> (raw)

Handle AF_INET6 for events:
 - NETEVENT_NEIGH_UPDATE
 - FIB_EVENT_ENTRY_REPLACE
 - FIB_EVENT_ENTRY_DEL

Also try to make wrappers for ipv4/6 specific functions.
This allow us to pass fib_notifier_info for most cases.
E.g  prestera_util_fen_info_copy, prestera_util_fen_info_release.
Main idea is to increase number of agnostic about ip version functions.

Limitations:
- Only "local" and "main" tables supported
- Only generic interfaces supported for router (no bridges or vlans)

Co-developed-by: Taras Chornyi <taras.chornyi@plvision.eu>
Signed-off-by: Taras Chornyi <taras.chornyi@plvision.eu>
Co-developed-by: Elad Nachman <enachman@marvell.com>
Signed-off-by: Elad Nachman <enachman@marvell.com>
Signed-off-by: Yevhen Orlov <yevhen.orlov@plvision.eu>
---
 .../marvell/prestera/prestera_router.c        | 138 +++++++++++++-----
 1 file changed, 101 insertions(+), 37 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_router.c b/drivers/net/ethernet/marvell/prestera/prestera_router.c
index a9a1028cb17b..5ee0a9511878 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_router.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_router.c
@@ -12,6 +12,7 @@
 #include <linux/if_vlan.h>
 #include <linux/if_macvlan.h>
 #include <net/netevent.h>
+#include <net/ip6_route.h>
 
 #include "prestera.h"
 #include "prestera_router_hw.h"
@@ -60,6 +61,7 @@ struct prestera_kern_fib_cache {
 	union {
 		struct fib_notifier_info info; /* point to any of 4/6 */
 		struct fib_entry_notifier_info fen4_info;
+		struct fib6_entry_notifier_info fen6_info;
 	};
 	bool reachable;
 };
@@ -89,18 +91,67 @@ static u32 prestera_fix_tb_id(u32 tb_id)
 	return tb_id;
 }
 
+static void
+prestera_util_fen_info_copy(struct fib_notifier_info *sinfo,
+			    struct fib_notifier_info *tinfo)
+{
+	struct fib6_entry_notifier_info *sinfo6 =
+		container_of(sinfo, struct fib6_entry_notifier_info, info);
+	struct fib_entry_notifier_info *sinfo4 =
+		container_of(sinfo, struct fib_entry_notifier_info, info);
+	struct fib6_entry_notifier_info *tinfo6 =
+		container_of(tinfo, struct fib6_entry_notifier_info, info);
+	struct fib_entry_notifier_info *tinfo4 =
+		container_of(tinfo, struct fib_entry_notifier_info, info);
+
+	if (sinfo->family == AF_INET) {
+		fib_info_hold(sinfo4->fi);
+		*tinfo4 = *sinfo4;
+	} else if (sinfo->family == AF_INET6) {
+		fib6_info_hold(sinfo6->rt);
+		*tinfo6 = *sinfo6;
+	} else {
+		WARN(1, "Invalid address family %s %d", __func__, sinfo->family);
+	}
+}
+
+static void prestera_util_fen_info_release(struct fib_notifier_info *info)
+{
+	struct fib6_entry_notifier_info *info6 =
+		container_of(info, struct fib6_entry_notifier_info, info);
+	struct fib_entry_notifier_info *info4 =
+		container_of(info, struct fib_entry_notifier_info, info);
+
+	if (info->family == AF_INET)
+		fib_info_put(info4->fi);
+	else if (info->family == AF_INET6)
+		fib6_info_release(info6->rt);
+	else
+		WARN(1, "Invalid address family %s %d",
+		     __func__, info->family);
+}
+
 static void
 prestera_util_fen_info2fib_cache_key(struct fib_notifier_info *info,
 				     struct prestera_kern_fib_cache_key *key)
 {
+	struct fib6_entry_notifier_info *fen6_info =
+		container_of(info, struct fib6_entry_notifier_info, info);
 	struct fib_entry_notifier_info *fen_info =
 		container_of(info, struct fib_entry_notifier_info, info);
 
 	memset(key, 0, sizeof(*key));
-	key->addr.v = PRESTERA_IPV4;
-	key->addr.u.ipv4 = cpu_to_be32(fen_info->dst);
-	key->prefix_len = fen_info->dst_len;
-	key->kern_tb_id = fen_info->tb_id;
+	if (info->family == AF_INET) {
+		key->addr.v = PRESTERA_IPV4;
+		key->addr.u.ipv4 = cpu_to_be32(fen_info->dst);
+		key->prefix_len = fen_info->dst_len;
+		key->kern_tb_id = fen_info->tb_id;
+	} else if (info->family == AF_INET6) {
+		key->addr.v = PRESTERA_IPV6;
+		key->addr.u.ipv6 = fen6_info->rt->fib6_dst.addr;
+		key->prefix_len = fen6_info->rt->fib6_dst.plen;
+		key->kern_tb_id = fen6_info->rt->fib6_table->tb6_id;
+	}
 }
 
 static int prestera_util_nhc2nc_key(struct prestera_switch *sw,
@@ -155,6 +206,9 @@ prestera_util_neigh2nc_key(struct prestera_switch *sw, struct neighbour *n,
 	if (n->tbl->family == AF_INET) {
 		key->addr.v = PRESTERA_IPV4;
 		key->addr.u.ipv4 = *(__be32 *)n->primary_key;
+	} else if (n->tbl->family == AF_INET6) {
+		key->addr.v = PRESTERA_IPV6;
+		key->addr.u.ipv6 = *(struct in6_addr *)n->primary_key;
 	} else {
 		return -ENOENT;
 	}
@@ -683,8 +737,15 @@ __prestera_k_arb_n_offload_set(struct prestera_switch *sw,
 {
 	struct neighbour *n;
 
-	n = neigh_lookup(&arp_tbl, &nc->key.addr.u.ipv4,
-			 nc->key.dev);
+	if (nc->key.addr.v == PRESTERA_IPV4)
+		n = neigh_lookup(&arp_tbl, &nc->key.addr.u.ipv4,
+				 nc->key.dev);
+	else if (nc->key.addr.v == PRESTERA_IPV6)
+		n = neigh_lookup(&nd_tbl, &nc->key.addr.u.ipv6,
+				 nc->key.dev);
+	else
+		n = NULL;
+
 	if (!n)
 		return;
 
@@ -715,7 +776,8 @@ __prestera_k_arb_fib_lpm_offload_set(struct prestera_switch *sw,
 		fib_alias_hw_flags_set(&init_net, &fri);
 		return;
 	case PRESTERA_IPV6:
-		/* TODO */
+		fib6_info_hw_flags_set(&init_net, fc->fen6_info.rt,
+				       offload, trap, fail);
 		return;
 	}
 }
@@ -1384,44 +1446,43 @@ static int __prestera_inetaddr_valid_cb(struct notifier_block *nb,
 struct prestera_fib_event_work {
 	struct work_struct work;
 	struct prestera_switch *sw;
-	struct fib_entry_notifier_info fen_info;
+	union {
+		struct fib_notifier_info info; /* point to any of 4/6 */
+		struct fib6_entry_notifier_info fen6_info;
+		struct fib_entry_notifier_info fen4_info;
+	};
 	unsigned long event;
 };
 
 static void __prestera_router_fib_event_work(struct work_struct *work)
 {
 	struct prestera_fib_event_work *fib_work =
-			container_of(work, struct prestera_fib_event_work, work);
-	struct prestera_switch *sw = fib_work->sw;
+		container_of(work, struct prestera_fib_event_work,
+			     work);
 	int err;
 
 	rtnl_lock();
 
 	switch (fib_work->event) {
 	case FIB_EVENT_ENTRY_REPLACE:
-		err = prestera_k_arb_fib_evt(sw, true,
-					     &fib_work->fen_info.info);
+		err = prestera_k_arb_fib_evt(fib_work->sw, true,
+					     &fib_work->info);
 		if (err)
-			goto err_out;
+			dev_err(fib_work->sw->dev->dev,
+				"Error when processing lpm entry");
 
 		break;
 	case FIB_EVENT_ENTRY_DEL:
-		err = prestera_k_arb_fib_evt(sw, false,
-					     &fib_work->fen_info.info);
+		err = prestera_k_arb_fib_evt(fib_work->sw, false,
+					     &fib_work->info);
 		if (err)
-			goto err_out;
+			dev_err(fib_work->sw->dev->dev,
+				"Cant delete lpm entry");
 
 		break;
 	}
 
-	goto out;
-
-err_out:
-	dev_err(sw->dev->dev, "Error when processing %pI4h/%d",
-		&fib_work->fen_info.dst,
-		fib_work->fen_info.dst_len);
-out:
-	fib_info_put(fib_work->fen_info.fi);
+	prestera_util_fen_info_release(&fib_work->info);
 	rtnl_unlock();
 	kfree(fib_work);
 }
@@ -1430,30 +1491,33 @@ static void __prestera_router_fib_event_work(struct work_struct *work)
 static int __prestera_router_fib_event(struct notifier_block *nb,
 				       unsigned long event, void *ptr)
 {
+	struct fib6_entry_notifier_info *info6 =
+		container_of(ptr, struct fib6_entry_notifier_info, info);
+	struct fib_entry_notifier_info *info4 =
+		container_of(ptr, struct fib_entry_notifier_info, info);
+	struct prestera_router *router =
+		container_of(nb, struct prestera_router, fib_nb);
 	struct prestera_fib_event_work *fib_work;
-	struct fib_entry_notifier_info *fen_info;
 	struct fib_notifier_info *info = ptr;
-	struct prestera_router *router;
-
-	if (info->family != AF_INET)
-		return NOTIFY_DONE;
-
-	router = container_of(nb, struct prestera_router, fib_nb);
 
 	switch (event) {
 	case FIB_EVENT_ENTRY_REPLACE:
 	case FIB_EVENT_ENTRY_DEL:
-		fen_info = container_of(info, struct fib_entry_notifier_info,
-					info);
-		if (!fen_info->fi)
+		if (info->family == AF_INET6) {
+			if (!info6->rt)
+				return NOTIFY_DONE;
+		} else if (info->family == AF_INET) {
+			if (!info4->fi)
+				return NOTIFY_DONE;
+		} else {
 			return NOTIFY_DONE;
+		}
 
 		fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
 		if (WARN_ON(!fib_work))
 			return NOTIFY_BAD;
 
-		fib_info_hold(fen_info->fi);
-		fib_work->fen_info = *fen_info;
+		prestera_util_fen_info_copy(info, &fib_work->info);
 		fib_work->event = event;
 		fib_work->sw = router->sw;
 		INIT_WORK(&fib_work->work, __prestera_router_fib_event_work);
@@ -1500,7 +1564,7 @@ static int prestera_router_netevent_event(struct notifier_block *nb,
 
 	switch (event) {
 	case NETEVENT_NEIGH_UPDATE:
-		if (n->tbl->family != AF_INET)
+		if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
 			return NOTIFY_DONE;
 
 		net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
-- 
2.17.1

             reply	other threads:[~2022-12-18 22:16 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-18 22:16 Yevhen Orlov [this message]
2022-12-23 11:48 ` [PATCH net-next v1 2/2] net: marvell: prestera: Handle ipv6 lpm/neigh events kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y5+RMvhZCyG0bFgh@yorlov.ow.s \
    --to=yevhen.orlov@plvision.eu \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mickeyr@marvell.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=serhiy.pshyk@plvision.eu \
    --cc=stephen@networkplumber.org \
    --cc=taras.chornyi@plvision.eu \
    --cc=volodymyr.mytnyk@plvision.eu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox