Skip to content

Commit 46a275a

Browse files
committed
Merge branch 'net-marvell-prestera-add-nexthop-routes-offloading'
Yevhen Orlov says: ==================== net: marvell: prestera: add nexthop routes offloading Add support for nexthop routes for Marvell Prestera driver. Subscribe on NEIGH_UPDATE events. Add features: - Support connected route adding e.g.: "ip address add 1.1.1.1/24 dev sw1p1" e.g.: "ip route add 6.6.6/24 dev sw1p1" - Support nexthop route adding e.g.: "ip route add 5.5.5/24 via 1.1.1.2" - Support ECMP route adding e.g.: "ip route add 5.5.5/24 nexthop via 1.1.1.2 nexthop via 1.1.1.3" - Support "offload" and "trap" flags per each nexthop - Support "offload" flag for neighbours Limitations: - Only "local" and "main" tables supported - Only generic interfaces supported for router (no bridges or vlans) Flags meaning: ip route add 5.5.5/24 nexthop via 2.2.2.2 nexthop via 2.2.2.3 ip route show ... 5.5.5.0/24 rt_offload nexthop via 2.2.2.2 dev sw1p31 weight 1 trap nexthop via 2.2.2.3 dev sw1p31 weight 1 trap ... # When you just add route - lpm entry became occupied # in HW ("rt_offload" flag), but related to nexthops neighbours # still not resolved ("trap" flag). # # After some time... ip route show ... 5.5.5.0/24 rt_offload nexthop via 2.2.2.2 dev sw1p31 weight 1 offload nexthop via 2.2.2.3 dev sw1p31 weight 1 offload ... # You will see, that appropriate neighbours was resolved and nexthop # entries occupied in HW too ("offload" flag) Co-developed-by: Taras Chornyi <tchornyi@marvell.com> Signed-off-by: Taras Chornyi <tchornyi@marvell.com> Co-developed-by: Oleksandr Mazur <oleksandr.mazur@plvision.eu> Signed-off-by: Oleksandr Mazur <oleksandr.mazur@plvision.eu> Signed-off-by: Yevhen Orlov <yevhen.orlov@plvision.eu> Changes for v2: * Add more reviewers in CC * Check if route nexthop or direct with fib_nh_gw_family instead of fib_nh_scope This is needed after, 747c143 ("ip: fix dflt addr selection for connected nexthop"), because direct route is now with the same scope as nexthop (RT_SCOPE_LINK) Changes for v3: * Resolve "unused functions" warnings, after patch ("net: marvell: prestera: Add heplers to interact ... "), and before patch ("net: marvell: prestera: Add neighbour cache accounting") Changes for v4: * Rebase to the latest master to resolve patch applying issues Changes for v5: * Repack structures to prevent holes * Remove unused variables * Fix misspeling issues Changes for v6: * Rebase on top of master * Fix smatch warnings Changes for v7: * Rebase on top of master * Refactor: use "fib_lookup" instead of "fib_new_table"+"fib_table_lookup", according to Paolo Abeni suggestion * Refactor: use "rhashtable_free_and_destroy" instead of rhashtable walk, according to Paolo Abeni suggestion ==================== Link: https://lore.kernel.org/r/20221001093417.22388-1-yevhen.orlov@plvision.eu Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 899b8cd + ae15ed6 commit 46a275a

File tree

7 files changed

+1683
-42
lines changed

7 files changed

+1683
-42
lines changed

drivers/net/ethernet/marvell/prestera/prestera.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,17 +306,27 @@ struct prestera_switch {
306306
struct prestera_counter *counter;
307307
u8 lag_member_max;
308308
u8 lag_max;
309+
u32 size_tbl_router_nexthop;
309310
};
310311

311312
struct prestera_router {
312313
struct prestera_switch *sw;
313314
struct list_head vr_list;
314315
struct list_head rif_entry_list;
316+
struct rhashtable nh_neigh_ht;
317+
struct rhashtable nexthop_group_ht;
315318
struct rhashtable fib_ht;
319+
struct rhashtable kern_neigh_cache_ht;
316320
struct rhashtable kern_fib_cache_ht;
317321
struct notifier_block inetaddr_nb;
318322
struct notifier_block inetaddr_valid_nb;
319323
struct notifier_block fib_nb;
324+
struct notifier_block netevent_nb;
325+
u8 *nhgrp_hw_state_cache; /* Bitmap cached hw state of nhs */
326+
unsigned long nhgrp_hw_cache_kick; /* jiffies */
327+
struct {
328+
struct delayed_work dw;
329+
} neighs_update;
320330
};
321331

322332
struct prestera_rxtx_params {
@@ -362,6 +372,8 @@ int prestera_port_cfg_mac_write(struct prestera_port *port,
362372
struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);
363373

364374
void prestera_queue_work(struct work_struct *work);
375+
void prestera_queue_delayed_work(struct delayed_work *work, unsigned long delay);
376+
void prestera_queue_drain(void);
365377

366378
int prestera_port_learning_set(struct prestera_port *port, bool learn_enable);
367379
int prestera_port_uc_flood_set(struct prestera_port *port, bool flood);

drivers/net/ethernet/marvell/prestera/prestera_hw.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010
#include "prestera_hw.h"
1111
#include "prestera_acl.h"
1212
#include "prestera_counter.h"
13+
#include "prestera_router_hw.h"
1314

1415
#define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
1516

1617
#define PRESTERA_MIN_MTU 64
1718

19+
#define PRESTERA_MSG_CHUNK_SIZE 1024
20+
1821
enum prestera_cmd_type_t {
1922
PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
2023
PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
@@ -57,6 +60,10 @@ enum prestera_cmd_type_t {
5760
PRESTERA_CMD_TYPE_ROUTER_RIF_DELETE = 0x601,
5861
PRESTERA_CMD_TYPE_ROUTER_LPM_ADD = 0x610,
5962
PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE = 0x611,
63+
PRESTERA_CMD_TYPE_ROUTER_NH_GRP_SET = 0x622,
64+
PRESTERA_CMD_TYPE_ROUTER_NH_GRP_BLK_GET = 0x645,
65+
PRESTERA_CMD_TYPE_ROUTER_NH_GRP_ADD = 0x623,
66+
PRESTERA_CMD_TYPE_ROUTER_NH_GRP_DELETE = 0x624,
6067
PRESTERA_CMD_TYPE_ROUTER_VR_CREATE = 0x630,
6168
PRESTERA_CMD_TYPE_ROUTER_VR_DELETE = 0x631,
6269

@@ -542,6 +549,14 @@ struct prestera_msg_ip_addr {
542549
u8 __pad[3];
543550
};
544551

552+
struct prestera_msg_nh {
553+
struct prestera_msg_iface oif;
554+
__le32 hw_id;
555+
u8 mac[ETH_ALEN];
556+
u8 is_active;
557+
u8 pad;
558+
};
559+
545560
struct prestera_msg_rif_req {
546561
struct prestera_msg_cmd cmd;
547562
struct prestera_msg_iface iif;
@@ -567,6 +582,34 @@ struct prestera_msg_lpm_req {
567582
u8 __pad[2];
568583
};
569584

585+
struct prestera_msg_nh_req {
586+
struct prestera_msg_cmd cmd;
587+
struct prestera_msg_nh nh[PRESTERA_NHGR_SIZE_MAX];
588+
__le32 size;
589+
__le32 grp_id;
590+
};
591+
592+
struct prestera_msg_nh_chunk_req {
593+
struct prestera_msg_cmd cmd;
594+
__le32 offset;
595+
};
596+
597+
struct prestera_msg_nh_chunk_resp {
598+
struct prestera_msg_ret ret;
599+
u8 hw_state[PRESTERA_MSG_CHUNK_SIZE];
600+
};
601+
602+
struct prestera_msg_nh_grp_req {
603+
struct prestera_msg_cmd cmd;
604+
__le32 grp_id;
605+
__le32 size;
606+
};
607+
608+
struct prestera_msg_nh_grp_resp {
609+
struct prestera_msg_ret ret;
610+
__le32 grp_id;
611+
};
612+
570613
struct prestera_msg_vr_req {
571614
struct prestera_msg_cmd cmd;
572615
__le16 vr_id;
@@ -729,11 +772,15 @@ static void prestera_hw_build_tests(void)
729772
BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_ports_reset_req) != 8);
730773
BUILD_BUG_ON(sizeof(struct prestera_msg_mdb_create_req) != 16);
731774
BUILD_BUG_ON(sizeof(struct prestera_msg_mdb_destroy_req) != 16);
775+
BUILD_BUG_ON(sizeof(struct prestera_msg_nh_req) != 124);
776+
BUILD_BUG_ON(sizeof(struct prestera_msg_nh_chunk_req) != 8);
777+
BUILD_BUG_ON(sizeof(struct prestera_msg_nh_grp_req) != 12);
732778

733779
/* structure that are part of req/resp fw messages */
734780
BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
735781
BUILD_BUG_ON(sizeof(struct prestera_msg_ip_addr) != 20);
736782
BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_port) != 12);
783+
BUILD_BUG_ON(sizeof(struct prestera_msg_nh) != 28);
737784

738785
/* check responses */
739786
BUILD_BUG_ON(sizeof(struct prestera_msg_common_resp) != 8);
@@ -750,6 +797,8 @@ static void prestera_hw_build_tests(void)
750797
BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
751798
BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);
752799
BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_create_resp) != 12);
800+
BUILD_BUG_ON(sizeof(struct prestera_msg_nh_chunk_resp) != 1032);
801+
BUILD_BUG_ON(sizeof(struct prestera_msg_nh_grp_resp) != 12);
753802

754803
/* check events */
755804
BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
@@ -1027,6 +1076,8 @@ int prestera_hw_switch_init(struct prestera_switch *sw)
10271076
sw->id = resp.switch_id;
10281077
sw->lag_member_max = resp.lag_member_max;
10291078
sw->lag_max = resp.lag_max;
1079+
sw->size_tbl_router_nexthop =
1080+
__le32_to_cpu(resp.size_tbl_router_nexthop);
10301081

10311082
return 0;
10321083
}
@@ -2037,6 +2088,85 @@ int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id,
20372088
sizeof(req));
20382089
}
20392090

2091+
int prestera_hw_nh_entries_set(struct prestera_switch *sw, int count,
2092+
struct prestera_neigh_info *nhs, u32 grp_id)
2093+
{
2094+
struct prestera_msg_nh_req req = { .size = __cpu_to_le32((u32)count),
2095+
.grp_id = __cpu_to_le32(grp_id) };
2096+
int i, err;
2097+
2098+
for (i = 0; i < count; i++) {
2099+
req.nh[i].is_active = nhs[i].connected;
2100+
memcpy(&req.nh[i].mac, nhs[i].ha, ETH_ALEN);
2101+
err = prestera_iface_to_msg(&nhs[i].iface, &req.nh[i].oif);
2102+
if (err)
2103+
return err;
2104+
}
2105+
2106+
return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_NH_GRP_SET, &req.cmd,
2107+
sizeof(req));
2108+
}
2109+
2110+
int prestera_hw_nhgrp_blk_get(struct prestera_switch *sw,
2111+
u8 *hw_state, u32 buf_size /* Buffer in bytes */)
2112+
{
2113+
static struct prestera_msg_nh_chunk_resp resp;
2114+
struct prestera_msg_nh_chunk_req req;
2115+
u32 buf_offset;
2116+
int err;
2117+
2118+
memset(&hw_state[0], 0, buf_size);
2119+
buf_offset = 0;
2120+
while (1) {
2121+
if (buf_offset >= buf_size)
2122+
break;
2123+
2124+
memset(&req, 0, sizeof(req));
2125+
req.offset = __cpu_to_le32(buf_offset * 8); /* 8 bits in u8 */
2126+
err = prestera_cmd_ret(sw,
2127+
PRESTERA_CMD_TYPE_ROUTER_NH_GRP_BLK_GET,
2128+
&req.cmd, sizeof(req), &resp.ret,
2129+
sizeof(resp));
2130+
if (err)
2131+
return err;
2132+
2133+
memcpy(&hw_state[buf_offset], &resp.hw_state[0],
2134+
buf_offset + PRESTERA_MSG_CHUNK_SIZE > buf_size ?
2135+
buf_size - buf_offset : PRESTERA_MSG_CHUNK_SIZE);
2136+
buf_offset += PRESTERA_MSG_CHUNK_SIZE;
2137+
}
2138+
2139+
return 0;
2140+
}
2141+
2142+
int prestera_hw_nh_group_create(struct prestera_switch *sw, u16 nh_count,
2143+
u32 *grp_id)
2144+
{
2145+
struct prestera_msg_nh_grp_req req = { .size = __cpu_to_le32((u32)nh_count) };
2146+
struct prestera_msg_nh_grp_resp resp;
2147+
int err;
2148+
2149+
err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_ROUTER_NH_GRP_ADD,
2150+
&req.cmd, sizeof(req), &resp.ret, sizeof(resp));
2151+
if (err)
2152+
return err;
2153+
2154+
*grp_id = __le32_to_cpu(resp.grp_id);
2155+
return err;
2156+
}
2157+
2158+
int prestera_hw_nh_group_delete(struct prestera_switch *sw, u16 nh_count,
2159+
u32 grp_id)
2160+
{
2161+
struct prestera_msg_nh_grp_req req = {
2162+
.grp_id = __cpu_to_le32(grp_id),
2163+
.size = __cpu_to_le32(nh_count)
2164+
};
2165+
2166+
return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_NH_GRP_DELETE,
2167+
&req.cmd, sizeof(req));
2168+
}
2169+
20402170
int prestera_hw_rxtx_init(struct prestera_switch *sw,
20412171
struct prestera_rxtx_params *params)
20422172
{

drivers/net/ethernet/marvell/prestera/prestera_hw.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ struct prestera_counter_stats;
146146
struct prestera_iface;
147147
struct prestera_flood_domain;
148148
struct prestera_mdb_entry;
149+
struct prestera_neigh_info;
149150

150151
/* Switch API */
151152
int prestera_hw_switch_init(struct prestera_switch *sw);
@@ -266,6 +267,16 @@ int prestera_hw_lpm_add(struct prestera_switch *sw, u16 vr_id,
266267
int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id,
267268
__be32 dst, u32 dst_len);
268269

270+
/* NH API */
271+
int prestera_hw_nh_entries_set(struct prestera_switch *sw, int count,
272+
struct prestera_neigh_info *nhs, u32 grp_id);
273+
int prestera_hw_nhgrp_blk_get(struct prestera_switch *sw,
274+
u8 *hw_state, u32 buf_size /* Buffer in bytes */);
275+
int prestera_hw_nh_group_create(struct prestera_switch *sw, u16 nh_count,
276+
u32 *grp_id);
277+
int prestera_hw_nh_group_delete(struct prestera_switch *sw, u16 nh_count,
278+
u32 grp_id);
279+
269280
/* Event handlers */
270281
int prestera_hw_event_handler_register(struct prestera_switch *sw,
271282
enum prestera_event_type type,

drivers/net/ethernet/marvell/prestera/prestera_main.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ void prestera_queue_work(struct work_struct *work)
3636
queue_work(prestera_owq, work);
3737
}
3838

39+
void prestera_queue_delayed_work(struct delayed_work *work, unsigned long delay)
40+
{
41+
queue_delayed_work(prestera_wq, work, delay);
42+
}
43+
44+
void prestera_queue_drain(void)
45+
{
46+
drain_workqueue(prestera_wq);
47+
drain_workqueue(prestera_owq);
48+
}
49+
3950
int prestera_port_learning_set(struct prestera_port *port, bool learn)
4051
{
4152
return prestera_hw_port_learning_set(port, learn);

0 commit comments

Comments
 (0)