162306a36Sopenharmony_ci/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ 262306a36Sopenharmony_ci/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#ifndef _MLXSW_ROUTER_H_ 562306a36Sopenharmony_ci#define _MLXSW_ROUTER_H_ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "spectrum.h" 862306a36Sopenharmony_ci#include "reg.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistruct mlxsw_sp_router_nve_decap { 1162306a36Sopenharmony_ci u32 ul_tb_id; 1262306a36Sopenharmony_ci u32 tunnel_index; 1362306a36Sopenharmony_ci enum mlxsw_sp_l3proto ul_proto; 1462306a36Sopenharmony_ci union mlxsw_sp_l3addr ul_sip; 1562306a36Sopenharmony_ci u8 valid:1; 1662306a36Sopenharmony_ci}; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* gen_pool_alloc() returns 0 when allocation fails, so use an offset */ 1962306a36Sopenharmony_ci#define MLXSW_SP_ROUTER_GENALLOC_OFFSET 0x100 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistruct mlxsw_sp_router { 2262306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp; 2362306a36Sopenharmony_ci struct rhashtable crif_ht; 2462306a36Sopenharmony_ci struct gen_pool *rifs_table; 2562306a36Sopenharmony_ci struct mlxsw_sp_rif **rifs; 2662306a36Sopenharmony_ci struct idr rif_mac_profiles_idr; 2762306a36Sopenharmony_ci atomic_t rif_mac_profiles_count; 2862306a36Sopenharmony_ci atomic_t rifs_count; 2962306a36Sopenharmony_ci u8 max_rif_mac_profile; 3062306a36Sopenharmony_ci struct mlxsw_sp_vr *vrs; 3162306a36Sopenharmony_ci struct rhashtable neigh_ht; 3262306a36Sopenharmony_ci struct rhashtable nexthop_group_ht; 3362306a36Sopenharmony_ci struct rhashtable nexthop_ht; 3462306a36Sopenharmony_ci struct list_head nexthop_list; 3562306a36Sopenharmony_ci struct { 3662306a36Sopenharmony_ci /* One tree for each protocol: IPv4 and IPv6 */ 3762306a36Sopenharmony_ci struct mlxsw_sp_lpm_tree *proto_trees[2]; 3862306a36Sopenharmony_ci struct mlxsw_sp_lpm_tree *trees; 3962306a36Sopenharmony_ci unsigned int tree_count; 4062306a36Sopenharmony_ci } lpm; 4162306a36Sopenharmony_ci struct { 4262306a36Sopenharmony_ci struct delayed_work dw; 4362306a36Sopenharmony_ci unsigned long interval; /* ms */ 4462306a36Sopenharmony_ci atomic_t neigh_count; 4562306a36Sopenharmony_ci } neighs_update; 4662306a36Sopenharmony_ci struct delayed_work nexthop_probe_dw; 4762306a36Sopenharmony_ci#define MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL 5000 /* ms */ 4862306a36Sopenharmony_ci struct list_head nexthop_neighs_list; 4962306a36Sopenharmony_ci struct list_head ipip_list; 5062306a36Sopenharmony_ci struct notifier_block nexthop_nb; 5162306a36Sopenharmony_ci struct notifier_block fib_nb; 5262306a36Sopenharmony_ci struct notifier_block netevent_nb; 5362306a36Sopenharmony_ci struct notifier_block inetaddr_nb; 5462306a36Sopenharmony_ci struct notifier_block inet6addr_nb; 5562306a36Sopenharmony_ci struct notifier_block netdevice_nb; 5662306a36Sopenharmony_ci struct notifier_block inetaddr_valid_nb; 5762306a36Sopenharmony_ci struct notifier_block inet6addr_valid_nb; 5862306a36Sopenharmony_ci const struct mlxsw_sp_rif_ops **rif_ops_arr; 5962306a36Sopenharmony_ci const struct mlxsw_sp_ipip_ops **ipip_ops_arr; 6062306a36Sopenharmony_ci struct mlxsw_sp_router_nve_decap nve_decap_config; 6162306a36Sopenharmony_ci struct mutex lock; /* Protects shared router resources */ 6262306a36Sopenharmony_ci struct mlxsw_sp_fib_entry_op_ctx *ll_op_ctx; 6362306a36Sopenharmony_ci struct mlxsw_sp_crif *lb_crif; 6462306a36Sopenharmony_ci const struct mlxsw_sp_adj_grp_size_range *adj_grp_size_ranges; 6562306a36Sopenharmony_ci size_t adj_grp_size_ranges_count; 6662306a36Sopenharmony_ci struct delayed_work nh_grp_activity_dw; 6762306a36Sopenharmony_ci struct list_head nh_res_grp_list; 6862306a36Sopenharmony_ci bool inc_parsing_depth; 6962306a36Sopenharmony_ci refcount_t num_groups; 7062306a36Sopenharmony_ci u32 adj_trap_index; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistruct mlxsw_sp_rif_ipip_lb; 7462306a36Sopenharmony_cistruct mlxsw_sp_rif_ipip_lb_config { 7562306a36Sopenharmony_ci enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt; 7662306a36Sopenharmony_ci u32 okey; 7762306a36Sopenharmony_ci enum mlxsw_sp_l3proto ul_protocol; /* Underlay. */ 7862306a36Sopenharmony_ci union mlxsw_sp_l3addr saddr; 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cienum mlxsw_sp_rif_counter_dir { 8262306a36Sopenharmony_ci MLXSW_SP_RIF_COUNTER_INGRESS, 8362306a36Sopenharmony_ci MLXSW_SP_RIF_COUNTER_EGRESS, 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistruct mlxsw_sp_neigh_entry; 8762306a36Sopenharmony_cistruct mlxsw_sp_nexthop; 8862306a36Sopenharmony_cistruct mlxsw_sp_ipip_entry; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistruct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp, 9162306a36Sopenharmony_ci u16 rif_index); 9262306a36Sopenharmony_ciu16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *rif); 9362306a36Sopenharmony_ciu16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif); 9462306a36Sopenharmony_ciu16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif); 9562306a36Sopenharmony_ciu32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev); 9662306a36Sopenharmony_ciint mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif); 9762306a36Sopenharmony_cibool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif); 9862306a36Sopenharmony_cibool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif, 9962306a36Sopenharmony_ci const struct net_device *dev); 10062306a36Sopenharmony_ciint mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp, 10162306a36Sopenharmony_ci struct mlxsw_sp_rif *rif, 10262306a36Sopenharmony_ci enum mlxsw_sp_rif_counter_dir dir, 10362306a36Sopenharmony_ci u64 *cnt); 10462306a36Sopenharmony_civoid mlxsw_sp_rif_counter_free(struct mlxsw_sp_rif *rif, 10562306a36Sopenharmony_ci enum mlxsw_sp_rif_counter_dir dir); 10662306a36Sopenharmony_ciint mlxsw_sp_rif_counter_alloc(struct mlxsw_sp_rif *rif, 10762306a36Sopenharmony_ci enum mlxsw_sp_rif_counter_dir dir); 10862306a36Sopenharmony_cistruct mlxsw_sp_neigh_entry * 10962306a36Sopenharmony_cimlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif, 11062306a36Sopenharmony_ci struct mlxsw_sp_neigh_entry *neigh_entry); 11162306a36Sopenharmony_ciint mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry); 11262306a36Sopenharmony_ciunsigned char * 11362306a36Sopenharmony_cimlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry); 11462306a36Sopenharmony_ciu32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry); 11562306a36Sopenharmony_cistruct in6_addr * 11662306a36Sopenharmony_cimlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) \ 11962306a36Sopenharmony_ci for (neigh_entry = mlxsw_sp_rif_neigh_next(rif, NULL); neigh_entry; \ 12062306a36Sopenharmony_ci neigh_entry = mlxsw_sp_rif_neigh_next(rif, neigh_entry)) 12162306a36Sopenharmony_ciint mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp, 12262306a36Sopenharmony_ci struct mlxsw_sp_neigh_entry *neigh_entry, 12362306a36Sopenharmony_ci u64 *p_counter); 12462306a36Sopenharmony_civoid 12562306a36Sopenharmony_cimlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp, 12662306a36Sopenharmony_ci struct mlxsw_sp_neigh_entry *neigh_entry, 12762306a36Sopenharmony_ci bool adding); 12862306a36Sopenharmony_cibool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry); 12962306a36Sopenharmony_ciint __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp *mlxsw_sp, 13062306a36Sopenharmony_ci struct mlxsw_sp_ipip_entry *ipip_entry, 13162306a36Sopenharmony_ci bool recreate_loopback, 13262306a36Sopenharmony_ci bool keep_encap, 13362306a36Sopenharmony_ci bool update_nexthops, 13462306a36Sopenharmony_ci struct netlink_ext_ack *extack); 13562306a36Sopenharmony_civoid mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp *mlxsw_sp, 13662306a36Sopenharmony_ci struct mlxsw_sp_ipip_entry *ipip_entry); 13762306a36Sopenharmony_cibool 13862306a36Sopenharmony_cimlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp *mlxsw_sp, 13962306a36Sopenharmony_ci enum mlxsw_sp_l3proto ul_proto, 14062306a36Sopenharmony_ci union mlxsw_sp_l3addr saddr, 14162306a36Sopenharmony_ci u32 ul_tb_id, 14262306a36Sopenharmony_ci const struct mlxsw_sp_ipip_entry *except); 14362306a36Sopenharmony_cistruct mlxsw_sp_nexthop *mlxsw_sp_nexthop_next(struct mlxsw_sp_router *router, 14462306a36Sopenharmony_ci struct mlxsw_sp_nexthop *nh); 14562306a36Sopenharmony_cibool mlxsw_sp_nexthop_is_forward(const struct mlxsw_sp_nexthop *nh); 14662306a36Sopenharmony_ciunsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop *nh); 14762306a36Sopenharmony_ciint mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index, 14862306a36Sopenharmony_ci u32 *p_adj_size, u32 *p_adj_hash_index); 14962306a36Sopenharmony_cistruct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh); 15062306a36Sopenharmony_cibool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh); 15162306a36Sopenharmony_ci#define mlxsw_sp_nexthop_for_each(nh, router) \ 15262306a36Sopenharmony_ci for (nh = mlxsw_sp_nexthop_next(router, NULL); nh; \ 15362306a36Sopenharmony_ci nh = mlxsw_sp_nexthop_next(router, nh)) 15462306a36Sopenharmony_ciint mlxsw_sp_nexthop_counter_get(struct mlxsw_sp *mlxsw_sp, 15562306a36Sopenharmony_ci struct mlxsw_sp_nexthop *nh, u64 *p_counter); 15662306a36Sopenharmony_ciint mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index, 15762306a36Sopenharmony_ci struct mlxsw_sp_nexthop *nh, bool force, 15862306a36Sopenharmony_ci char *ratr_pl); 15962306a36Sopenharmony_civoid mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp *mlxsw_sp, 16062306a36Sopenharmony_ci struct mlxsw_sp_nexthop *nh); 16162306a36Sopenharmony_civoid mlxsw_sp_nexthop_counter_free(struct mlxsw_sp *mlxsw_sp, 16262306a36Sopenharmony_ci struct mlxsw_sp_nexthop *nh); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic inline bool mlxsw_sp_l3addr_eq(const union mlxsw_sp_l3addr *addr1, 16562306a36Sopenharmony_ci const union mlxsw_sp_l3addr *addr2) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci return !memcmp(addr1, addr2, sizeof(*addr1)); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ciint mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp); 17162306a36Sopenharmony_ciint mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp); 17262306a36Sopenharmony_cistruct net_device * 17362306a36Sopenharmony_cimlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev); 17462306a36Sopenharmony_ciint mlxsw_sp_router_bridge_vlan_add(struct mlxsw_sp *mlxsw_sp, 17562306a36Sopenharmony_ci struct net_device *dev, 17662306a36Sopenharmony_ci u16 new_vid, bool is_pvid, 17762306a36Sopenharmony_ci struct netlink_ext_ack *extack); 17862306a36Sopenharmony_ciint mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, 17962306a36Sopenharmony_ci struct net_device *lag_dev, 18062306a36Sopenharmony_ci struct netlink_ext_ack *extack); 18162306a36Sopenharmony_civoid mlxsw_sp_router_port_leave_lag(struct mlxsw_sp_port *mlxsw_sp_port, 18262306a36Sopenharmony_ci struct net_device *lag_dev); 18362306a36Sopenharmony_ciint mlxsw_sp_netdevice_enslavement_replay(struct mlxsw_sp *mlxsw_sp, 18462306a36Sopenharmony_ci struct net_device *upper_dev, 18562306a36Sopenharmony_ci struct netlink_ext_ack *extack); 18662306a36Sopenharmony_civoid mlxsw_sp_netdevice_deslavement_replay(struct mlxsw_sp *mlxsw_sp, 18762306a36Sopenharmony_ci struct net_device *dev); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#endif /* _MLXSW_ROUTER_H_*/ 190