Commit 04f24a1e authored by Yevhen Orlov's avatar Yevhen Orlov Committed by Jakub Kicinski

net: marvell: prestera: Add heplers to interact with fib_notifier_info

This will be used to implement nexthops related logic in next patches.
Also try to keep ipv4/6 abstraction to be able to reuse helpers for ipv6
in the future.
Co-developed-by: default avatarTaras Chornyi <tchornyi@marvell.com>
Signed-off-by: default avatarTaras Chornyi <tchornyi@marvell.com>
Co-developed-by: default avatarOleksandr Mazur <oleksandr.mazur@plvision.eu>
Signed-off-by: default avatarOleksandr Mazur <oleksandr.mazur@plvision.eu>
Signed-off-by: default avatarYevhen Orlov <yevhen.orlov@plvision.eu>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 59b44ea8
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <net/inet_dscp.h> #include <net/inet_dscp.h>
#include <net/switchdev.h> #include <net/switchdev.h>
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
#include <net/nexthop.h>
#include "prestera.h" #include "prestera.h"
#include "prestera_router_hw.h" #include "prestera_router_hw.h"
...@@ -26,9 +27,10 @@ struct prestera_kern_fib_cache { ...@@ -26,9 +27,10 @@ struct prestera_kern_fib_cache {
} lpm_info; /* hold prepared lpm info */ } lpm_info; /* hold prepared lpm info */
/* Indicate if route is not overlapped by another table */ /* Indicate if route is not overlapped by another table */
struct rhash_head ht_node; /* node of prestera_router */ struct rhash_head ht_node; /* node of prestera_router */
struct fib_info *fi; union {
dscp_t kern_dscp; struct fib_notifier_info info; /* point to any of 4/6 */
u8 kern_type; struct fib_entry_notifier_info fen4_info;
};
bool reachable; bool reachable;
}; };
...@@ -51,15 +53,41 @@ static u32 prestera_fix_tb_id(u32 tb_id) ...@@ -51,15 +53,41 @@ static u32 prestera_fix_tb_id(u32 tb_id)
} }
static void static void
prestera_util_fen_info2fib_cache_key(struct fib_entry_notifier_info *fen_info, prestera_util_fen_info2fib_cache_key(struct fib_notifier_info *info,
struct prestera_kern_fib_cache_key *key) struct prestera_kern_fib_cache_key *key)
{ {
struct fib_entry_notifier_info *fen_info =
container_of(info, struct fib_entry_notifier_info, info);
memset(key, 0, sizeof(*key)); memset(key, 0, sizeof(*key));
key->addr.v = PRESTERA_IPV4;
key->addr.u.ipv4 = cpu_to_be32(fen_info->dst); key->addr.u.ipv4 = cpu_to_be32(fen_info->dst);
key->prefix_len = fen_info->dst_len; key->prefix_len = fen_info->dst_len;
key->kern_tb_id = fen_info->tb_id; key->kern_tb_id = fen_info->tb_id;
} }
static unsigned char
prestera_kern_fib_info_type(struct fib_notifier_info *info)
{
struct fib6_entry_notifier_info *fen6_info;
struct fib_entry_notifier_info *fen4_info;
if (info->family == AF_INET) {
fen4_info = container_of(info, struct fib_entry_notifier_info,
info);
return fen4_info->fi->fib_type;
} else if (info->family == AF_INET6) {
fen6_info = container_of(info, struct fib6_entry_notifier_info,
info);
/* TODO: ECMP in ipv6 is several routes.
* Every route has single nh.
*/
return fen6_info->rt->fib6_type;
}
return RTN_UNSPEC;
}
static struct prestera_kern_fib_cache * static struct prestera_kern_fib_cache *
prestera_kern_fib_cache_find(struct prestera_switch *sw, prestera_kern_fib_cache_find(struct prestera_switch *sw,
struct prestera_kern_fib_cache_key *key) struct prestera_kern_fib_cache_key *key)
...@@ -76,7 +104,7 @@ static void ...@@ -76,7 +104,7 @@ static void
__prestera_kern_fib_cache_destruct(struct prestera_switch *sw, __prestera_kern_fib_cache_destruct(struct prestera_switch *sw,
struct prestera_kern_fib_cache *fib_cache) struct prestera_kern_fib_cache *fib_cache)
{ {
fib_info_put(fib_cache->fi); fib_info_put(fib_cache->fen4_info.fi);
} }
static void static void
...@@ -96,8 +124,10 @@ prestera_kern_fib_cache_destroy(struct prestera_switch *sw, ...@@ -96,8 +124,10 @@ prestera_kern_fib_cache_destroy(struct prestera_switch *sw,
static struct prestera_kern_fib_cache * static struct prestera_kern_fib_cache *
prestera_kern_fib_cache_create(struct prestera_switch *sw, prestera_kern_fib_cache_create(struct prestera_switch *sw,
struct prestera_kern_fib_cache_key *key, struct prestera_kern_fib_cache_key *key,
struct fib_info *fi, dscp_t dscp, u8 type) struct fib_notifier_info *info)
{ {
struct fib_entry_notifier_info *fen_info =
container_of(info, struct fib_entry_notifier_info, info);
struct prestera_kern_fib_cache *fib_cache; struct prestera_kern_fib_cache *fib_cache;
int err; int err;
...@@ -106,10 +136,8 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw, ...@@ -106,10 +136,8 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw,
goto err_kzalloc; goto err_kzalloc;
memcpy(&fib_cache->key, key, sizeof(*key)); memcpy(&fib_cache->key, key, sizeof(*key));
fib_info_hold(fi); fib_info_hold(fen_info->fi);
fib_cache->fi = fi; memcpy(&fib_cache->fen4_info, fen_info, sizeof(*fen_info));
fib_cache->kern_dscp = dscp;
fib_cache->kern_type = type;
err = rhashtable_insert_fast(&sw->router->kern_fib_cache_ht, err = rhashtable_insert_fast(&sw->router->kern_fib_cache_ht,
&fib_cache->ht_node, &fib_cache->ht_node,
...@@ -120,7 +148,7 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw, ...@@ -120,7 +148,7 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw,
return fib_cache; return fib_cache;
err_ht_insert: err_ht_insert:
fib_info_put(fi); fib_info_put(fen_info->fi);
kfree(fib_cache); kfree(fib_cache);
err_kzalloc: err_kzalloc:
return NULL; return NULL;
...@@ -133,21 +161,25 @@ __prestera_k_arb_fib_lpm_offload_set(struct prestera_switch *sw, ...@@ -133,21 +161,25 @@ __prestera_k_arb_fib_lpm_offload_set(struct prestera_switch *sw,
{ {
struct fib_rt_info fri; struct fib_rt_info fri;
if (fc->key.addr.v != PRESTERA_IPV4) switch (fc->key.addr.v) {
return; case PRESTERA_IPV4:
fri.fi = fc->fen4_info.fi;
fri.fi = fc->fi;
fri.tb_id = fc->key.kern_tb_id; fri.tb_id = fc->key.kern_tb_id;
fri.dst = fc->key.addr.u.ipv4; fri.dst = fc->key.addr.u.ipv4;
fri.dst_len = fc->key.prefix_len; fri.dst_len = fc->key.prefix_len;
fri.dscp = fc->kern_dscp; fri.dscp = fc->fen4_info.dscp;
fri.type = fc->kern_type; fri.type = fc->fen4_info.type;
/* flags begin */ /* flags begin */
fri.offload = offload; fri.offload = offload;
fri.trap = trap; fri.trap = trap;
fri.offload_failed = fail; fri.offload_failed = fail;
/* flags end */ /* flags end */
fib_alias_hw_flags_set(&init_net, &fri); fib_alias_hw_flags_set(&init_net, &fri);
return;
case PRESTERA_IPV6:
/* TODO */
return;
}
} }
static int static int
...@@ -156,7 +188,7 @@ __prestera_pr_k_arb_fc_lpm_info_calc(struct prestera_switch *sw, ...@@ -156,7 +188,7 @@ __prestera_pr_k_arb_fc_lpm_info_calc(struct prestera_switch *sw,
{ {
memset(&fc->lpm_info, 0, sizeof(fc->lpm_info)); memset(&fc->lpm_info, 0, sizeof(fc->lpm_info));
switch (fc->fi->fib_type) { switch (prestera_kern_fib_info_type(&fc->info)) {
case RTN_UNICAST: case RTN_UNICAST:
fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_TRAP; fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_TRAP;
break; break;
...@@ -283,14 +315,14 @@ __prestera_k_arb_util_fib_overlapped(struct prestera_switch *sw, ...@@ -283,14 +315,14 @@ __prestera_k_arb_util_fib_overlapped(struct prestera_switch *sw,
static int static int
prestera_k_arb_fib_evt(struct prestera_switch *sw, prestera_k_arb_fib_evt(struct prestera_switch *sw,
bool replace, /* replace or del */ bool replace, /* replace or del */
struct fib_entry_notifier_info *fen_info) struct fib_notifier_info *info)
{ {
struct prestera_kern_fib_cache *tfib_cache, *bfib_cache; /* top/btm */ struct prestera_kern_fib_cache *tfib_cache, *bfib_cache; /* top/btm */
struct prestera_kern_fib_cache_key fc_key; struct prestera_kern_fib_cache_key fc_key;
struct prestera_kern_fib_cache *fib_cache; struct prestera_kern_fib_cache *fib_cache;
int err; int err;
prestera_util_fen_info2fib_cache_key(fen_info, &fc_key); prestera_util_fen_info2fib_cache_key(info, &fc_key);
fib_cache = prestera_kern_fib_cache_find(sw, &fc_key); fib_cache = prestera_kern_fib_cache_find(sw, &fc_key);
if (fib_cache) { if (fib_cache) {
fib_cache->reachable = false; fib_cache->reachable = false;
...@@ -313,10 +345,7 @@ prestera_k_arb_fib_evt(struct prestera_switch *sw, ...@@ -313,10 +345,7 @@ prestera_k_arb_fib_evt(struct prestera_switch *sw,
} }
if (replace) { if (replace) {
fib_cache = prestera_kern_fib_cache_create(sw, &fc_key, fib_cache = prestera_kern_fib_cache_create(sw, &fc_key, info);
fen_info->fi,
fen_info->dscp,
fen_info->type);
if (!fib_cache) { if (!fib_cache) {
dev_err(sw->dev->dev, "fib_cache == NULL"); dev_err(sw->dev->dev, "fib_cache == NULL");
return -ENOENT; return -ENOENT;
...@@ -508,13 +537,15 @@ static void __prestera_router_fib_event_work(struct work_struct *work) ...@@ -508,13 +537,15 @@ static void __prestera_router_fib_event_work(struct work_struct *work)
switch (fib_work->event) { switch (fib_work->event) {
case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_REPLACE:
err = prestera_k_arb_fib_evt(sw, true, &fib_work->fen_info); err = prestera_k_arb_fib_evt(sw, true,
&fib_work->fen_info.info);
if (err) if (err)
goto err_out; goto err_out;
break; break;
case FIB_EVENT_ENTRY_DEL: case FIB_EVENT_ENTRY_DEL:
err = prestera_k_arb_fib_evt(sw, false, &fib_work->fen_info); err = prestera_k_arb_fib_evt(sw, false,
&fib_work->fen_info.info);
if (err) if (err)
goto err_out; goto err_out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment