1*ab84be7eSDavid Ahern /* SPDX-License-Identifier: GPL-2.0 */ 2*ab84be7eSDavid Ahern /* 3*ab84be7eSDavid Ahern * Generic nexthop implementation 4*ab84be7eSDavid Ahern * 5*ab84be7eSDavid Ahern * Copyright (c) 2017-19 Cumulus Networks 6*ab84be7eSDavid Ahern * Copyright (c) 2017-19 David Ahern <dsa@cumulusnetworks.com> 7*ab84be7eSDavid Ahern */ 8*ab84be7eSDavid Ahern 9*ab84be7eSDavid Ahern #ifndef __LINUX_NEXTHOP_H 10*ab84be7eSDavid Ahern #define __LINUX_NEXTHOP_H 11*ab84be7eSDavid Ahern 12*ab84be7eSDavid Ahern #include <linux/netdevice.h> 13*ab84be7eSDavid Ahern #include <linux/types.h> 14*ab84be7eSDavid Ahern #include <net/ip_fib.h> 15*ab84be7eSDavid Ahern #include <net/netlink.h> 16*ab84be7eSDavid Ahern 17*ab84be7eSDavid Ahern #define NEXTHOP_VALID_USER_FLAGS RTNH_F_ONLINK 18*ab84be7eSDavid Ahern 19*ab84be7eSDavid Ahern struct nexthop; 20*ab84be7eSDavid Ahern 21*ab84be7eSDavid Ahern struct nh_config { 22*ab84be7eSDavid Ahern u32 nh_id; 23*ab84be7eSDavid Ahern 24*ab84be7eSDavid Ahern u8 nh_family; 25*ab84be7eSDavid Ahern u8 nh_protocol; 26*ab84be7eSDavid Ahern u8 nh_blackhole; 27*ab84be7eSDavid Ahern u32 nh_flags; 28*ab84be7eSDavid Ahern 29*ab84be7eSDavid Ahern int nh_ifindex; 30*ab84be7eSDavid Ahern struct net_device *dev; 31*ab84be7eSDavid Ahern 32*ab84be7eSDavid Ahern u32 nlflags; 33*ab84be7eSDavid Ahern struct nl_info nlinfo; 34*ab84be7eSDavid Ahern }; 35*ab84be7eSDavid Ahern 36*ab84be7eSDavid Ahern struct nh_info { 37*ab84be7eSDavid Ahern struct hlist_node dev_hash; /* entry on netns devhash */ 38*ab84be7eSDavid Ahern struct nexthop *nh_parent; 39*ab84be7eSDavid Ahern 40*ab84be7eSDavid Ahern u8 family; 41*ab84be7eSDavid Ahern bool reject_nh; 42*ab84be7eSDavid Ahern 43*ab84be7eSDavid Ahern union { 44*ab84be7eSDavid Ahern struct fib_nh_common fib_nhc; 45*ab84be7eSDavid Ahern }; 46*ab84be7eSDavid Ahern }; 47*ab84be7eSDavid Ahern 48*ab84be7eSDavid Ahern struct nexthop { 49*ab84be7eSDavid Ahern struct rb_node rb_node; /* entry on netns rbtree */ 50*ab84be7eSDavid Ahern struct net *net; 51*ab84be7eSDavid Ahern 52*ab84be7eSDavid Ahern u32 id; 53*ab84be7eSDavid Ahern 54*ab84be7eSDavid Ahern u8 protocol; /* app managing this nh */ 55*ab84be7eSDavid Ahern u8 nh_flags; 56*ab84be7eSDavid Ahern 57*ab84be7eSDavid Ahern refcount_t refcnt; 58*ab84be7eSDavid Ahern struct rcu_head rcu; 59*ab84be7eSDavid Ahern 60*ab84be7eSDavid Ahern union { 61*ab84be7eSDavid Ahern struct nh_info __rcu *nh_info; 62*ab84be7eSDavid Ahern }; 63*ab84be7eSDavid Ahern }; 64*ab84be7eSDavid Ahern 65*ab84be7eSDavid Ahern /* caller is holding rcu or rtnl; no reference taken to nexthop */ 66*ab84be7eSDavid Ahern struct nexthop *nexthop_find_by_id(struct net *net, u32 id); 67*ab84be7eSDavid Ahern void nexthop_free_rcu(struct rcu_head *head); 68*ab84be7eSDavid Ahern 69*ab84be7eSDavid Ahern static inline bool nexthop_get(struct nexthop *nh) 70*ab84be7eSDavid Ahern { 71*ab84be7eSDavid Ahern return refcount_inc_not_zero(&nh->refcnt); 72*ab84be7eSDavid Ahern } 73*ab84be7eSDavid Ahern 74*ab84be7eSDavid Ahern static inline void nexthop_put(struct nexthop *nh) 75*ab84be7eSDavid Ahern { 76*ab84be7eSDavid Ahern if (refcount_dec_and_test(&nh->refcnt)) 77*ab84be7eSDavid Ahern call_rcu(&nh->rcu, nexthop_free_rcu); 78*ab84be7eSDavid Ahern } 79*ab84be7eSDavid Ahern 80*ab84be7eSDavid Ahern /* called with rcu lock */ 81*ab84be7eSDavid Ahern static inline bool nexthop_is_blackhole(const struct nexthop *nh) 82*ab84be7eSDavid Ahern { 83*ab84be7eSDavid Ahern const struct nh_info *nhi; 84*ab84be7eSDavid Ahern 85*ab84be7eSDavid Ahern nhi = rcu_dereference(nh->nh_info); 86*ab84be7eSDavid Ahern return nhi->reject_nh; 87*ab84be7eSDavid Ahern } 88*ab84be7eSDavid Ahern #endif 89