From 97d5847b7ceba4ba9aaa7402ae3cc3da3eac2725 Mon Sep 17 00:00:00 2001 From: Yevhen Orlov Date: Mon, 19 Dec 2022 00:16:40 +0200 Subject: [PATCH] net: marvell: prestera: Add router ipv6 ABI There are only lpm add/del for ipv6 needed. Nexthops indexes shared with ipv4. Limitations: - Only "local" and "main" tables supported - Only generic interfaces supported for router (no bridges or vlans) Co-developed-by: Taras Chornyi Signed-off-by: Taras Chornyi Co-developed-by: Elad Nachman Signed-off-by: Elad Nachman Signed-off-by: Yevhen Orlov --- .../ethernet/marvell/prestera/prestera_hw.c | 34 +++++++++++++++++++ .../ethernet/marvell/prestera/prestera_hw.h | 4 +++ .../marvell/prestera/prestera_router_hw.c | 33 ++++++++++++++---- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/marvell/prestera/prestera_hw.c b/drivers/net/ethernet/marvell/prestera/prestera_hw.c index fc6f7d2746e887..13341056599a6c 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_hw.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_hw.c @@ -540,6 +540,11 @@ struct prestera_msg_iface { u8 __pad[3]; }; +enum prestera_msg_ip_addr_v { + PRESTERA_MSG_IPV4 = 0, + PRESTERA_MSG_IPV6 +}; + struct prestera_msg_ip_addr { union { __be32 ipv4; @@ -2088,6 +2093,35 @@ int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id, sizeof(req)); } +int prestera_hw_lpm6_add(struct prestera_switch *sw, u16 vr_id, + __u8 *dst, u32 dst_len, u32 grp_id) +{ + struct prestera_msg_lpm_req req; + + req.dst.v = PRESTERA_MSG_IPV6; + memcpy(&req.dst.u.ipv6, dst, 16); + req.dst_len = __cpu_to_le32(dst_len); + req.vr_id = __cpu_to_le16(vr_id); + req.grp_id = __cpu_to_le32(grp_id); + + return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_ADD, &req.cmd, + sizeof(req)); +} + +int prestera_hw_lpm6_del(struct prestera_switch *sw, u16 vr_id, + __u8 *dst, u32 dst_len) +{ + struct prestera_msg_lpm_req req; + + req.dst.v = PRESTERA_MSG_IPV6; + memcpy(&req.dst.u.ipv6, dst, 16); + req.dst_len = __cpu_to_le32(dst_len); + req.vr_id = __cpu_to_le16(vr_id); + + return prestera_cmd(sw, PRESTERA_CMD_TYPE_ROUTER_LPM_DELETE, &req.cmd, + sizeof(req)); +} + int prestera_hw_nh_entries_set(struct prestera_switch *sw, int count, struct prestera_neigh_info *nhs, u32 grp_id) { diff --git a/drivers/net/ethernet/marvell/prestera/prestera_hw.h b/drivers/net/ethernet/marvell/prestera/prestera_hw.h index 0a929279e1cea4..8769be6752bc0e 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_hw.h +++ b/drivers/net/ethernet/marvell/prestera/prestera_hw.h @@ -266,6 +266,10 @@ int prestera_hw_lpm_add(struct prestera_switch *sw, u16 vr_id, __be32 dst, u32 dst_len, u32 grp_id); int prestera_hw_lpm_del(struct prestera_switch *sw, u16 vr_id, __be32 dst, u32 dst_len); +int prestera_hw_lpm6_add(struct prestera_switch *sw, u16 vr_id, + __u8 *dst, u32 dst_len, u32 grp_id); +int prestera_hw_lpm6_del(struct prestera_switch *sw, u16 vr_id, + __u8 *dst, u32 dst_len); /* NH API */ int prestera_hw_nh_entries_set(struct prestera_switch *sw, int count, diff --git a/drivers/net/ethernet/marvell/prestera/prestera_router_hw.c b/drivers/net/ethernet/marvell/prestera/prestera_router_hw.c index 02faaea2aefaa6..1c6d0cdbdfdf90 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_router_hw.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_router_hw.c @@ -581,8 +581,16 @@ static void __prestera_fib_node_destruct(struct prestera_switch *sw, struct prestera_vr *vr; vr = fib_node->info.vr; - prestera_hw_lpm_del(sw, vr->hw_vr_id, fib_node->key.addr.u.ipv4, - fib_node->key.prefix_len); + if (fib_node->key.addr.v == PRESTERA_IPV4) + prestera_hw_lpm_del(sw, vr->hw_vr_id, fib_node->key.addr.u.ipv4, + fib_node->key.prefix_len); + else if (fib_node->key.addr.v == PRESTERA_IPV6) + prestera_hw_lpm6_del(sw, vr->hw_vr_id, + (u8 *)&fib_node->key.addr.u.ipv6.s6_addr, + fib_node->key.prefix_len); + else + WARN(1, "Invalid address version. Memory corrupted?"); + switch (fib_node->info.type) { case PRESTERA_FIB_TYPE_UC_NH: prestera_nexthop_group_put(sw, fib_node->info.nh_grp); @@ -661,8 +669,16 @@ prestera_fib_node_create(struct prestera_switch *sw, goto err_nh_grp_get; } - err = prestera_hw_lpm_add(sw, vr->hw_vr_id, key->addr.u.ipv4, - key->prefix_len, grp_id); + if (key->addr.v == PRESTERA_IPV4) + err = prestera_hw_lpm_add(sw, vr->hw_vr_id, key->addr.u.ipv4, + key->prefix_len, grp_id); + else if (key->addr.v == PRESTERA_IPV6) + err = prestera_hw_lpm6_add(sw, vr->hw_vr_id, + (u8 *)&key->addr.u.ipv6.s6_addr, + key->prefix_len, grp_id); + else + WARN(1, "Invalid address version. Memory corrupted?"); + if (err) goto err_lpm_add; @@ -674,8 +690,13 @@ prestera_fib_node_create(struct prestera_switch *sw, return fib_node; err_ht_insert: - prestera_hw_lpm_del(sw, vr->hw_vr_id, key->addr.u.ipv4, - key->prefix_len); + if (key->addr.v == PRESTERA_IPV4) + prestera_hw_lpm_del(sw, vr->hw_vr_id, key->addr.u.ipv4, + key->prefix_len); + else if (key->addr.v == PRESTERA_IPV6) + prestera_hw_lpm6_del(sw, vr->hw_vr_id, + (u8 *)&key->addr.u.ipv6.s6_addr, + key->prefix_len); err_lpm_add: if (fib_type == PRESTERA_FIB_TYPE_UC_NH) prestera_nexthop_group_put(sw, fib_node->info.nh_grp);