2022-12-18 22:58:51

by Yevhen Orlov

[permalink] [raw]
Subject: [PATCH net-next v1 2/2] net: marvell: prestera: Handle ipv6 lpm/neigh events

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 <[email protected]>
Signed-off-by: Taras Chornyi <[email protected]>
Co-developed-by: Elad Nachman <[email protected]>
Signed-off-by: Elad Nachman <[email protected]>
Signed-off-by: Yevhen Orlov <[email protected]>
---
.../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


2022-12-23 12:16:03

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH net-next v1 2/2] net: marvell: prestera: Handle ipv6 lpm/neigh events

Hi Yevhen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on net-next/master]

url: https://github.com/intel-lab-lkp/linux/commits/Yevhen-Orlov/net-marvell-prestera-add-ipv6-routes-offloading/20221220-035326
patch link: https://lore.kernel.org/r/Y5%2BRMvhZCyG0bFgh%40yorlov.ow.s
patch subject: [PATCH net-next v1 2/2] net: marvell: prestera: Handle ipv6 lpm/neigh events
config: x86_64-randconfig-a013-20221219
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/47f5532bdec74c057f205b5cc7e7e7ebaec3b63b
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Yevhen-Orlov/net-marvell-prestera-add-ipv6-routes-offloading/20221220-035326
git checkout 47f5532bdec74c057f205b5cc7e7e7ebaec3b63b
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

>> ld.lld: error: undefined symbol: fib6_info_destroy_rcu
>>> referenced by ip6_fib.h:340 (include/net/ip6_fib.h:340)
>>> vmlinux.o:(__prestera_router_fib_event_work)
--
>> ld.lld: error: undefined symbol: nd_tbl
>>> referenced by prestera_router.c:0 (drivers/net/ethernet/marvell/prestera/prestera_router.c:0)
>>> vmlinux.o:(__prestera_k_arb_n_offload_set)
--
>> ld.lld: error: undefined symbol: fib6_info_hw_flags_set
>>> referenced by prestera_router.c:779 (drivers/net/ethernet/marvell/prestera/prestera_router.c:779)
>>> vmlinux.o:(__prestera_k_arb_fib_lpm_offload_set)

--
0-DAY CI Kernel Test Service
https://01.org/lkp


Attachments:
(No filename) (2.22 kB)
config (158.61 kB)
Download all attachments