| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ | 
|---|
| 2 | /* | 
|---|
| 3 | * INET		An implementation of the TCP/IP protocol suite for the LINUX | 
|---|
| 4 | *		operating system.  INET  is implemented using the  BSD Socket | 
|---|
| 5 | *		interface as the means of communication with the user level. | 
|---|
| 6 | * | 
|---|
| 7 | *		Definitions for the Forwarding Information Base. | 
|---|
| 8 | * | 
|---|
| 9 | * Authors:	A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru> | 
|---|
| 10 | */ | 
|---|
| 11 |  | 
|---|
| 12 | #ifndef _NET_IP_FIB_H | 
|---|
| 13 | #define _NET_IP_FIB_H | 
|---|
| 14 |  | 
|---|
| 15 | #include <net/flow.h> | 
|---|
| 16 | #include <linux/seq_file.h> | 
|---|
| 17 | #include <linux/rcupdate.h> | 
|---|
| 18 | #include <net/fib_notifier.h> | 
|---|
| 19 | #include <net/fib_rules.h> | 
|---|
| 20 | #include <net/inet_dscp.h> | 
|---|
| 21 | #include <net/inetpeer.h> | 
|---|
| 22 | #include <linux/percpu.h> | 
|---|
| 23 | #include <linux/notifier.h> | 
|---|
| 24 | #include <linux/refcount.h> | 
|---|
| 25 | #include <linux/ip.h> | 
|---|
| 26 | #include <linux/in_route.h> | 
|---|
| 27 |  | 
|---|
| 28 | struct fib_config { | 
|---|
| 29 | u8			fc_dst_len; | 
|---|
| 30 | dscp_t			fc_dscp; | 
|---|
| 31 | u8			fc_protocol; | 
|---|
| 32 | u8			fc_scope; | 
|---|
| 33 | u8			fc_type; | 
|---|
| 34 | u8			fc_gw_family; | 
|---|
| 35 | /* 2 bytes unused */ | 
|---|
| 36 | u32			fc_table; | 
|---|
| 37 | __be32			fc_dst; | 
|---|
| 38 | union { | 
|---|
| 39 | __be32		fc_gw4; | 
|---|
| 40 | struct in6_addr	fc_gw6; | 
|---|
| 41 | }; | 
|---|
| 42 | int			fc_oif; | 
|---|
| 43 | u32			fc_flags; | 
|---|
| 44 | u32			fc_priority; | 
|---|
| 45 | __be32			fc_prefsrc; | 
|---|
| 46 | u32			fc_nh_id; | 
|---|
| 47 | struct nlattr		*fc_mx; | 
|---|
| 48 | struct rtnexthop	*fc_mp; | 
|---|
| 49 | int			fc_mx_len; | 
|---|
| 50 | int			fc_mp_len; | 
|---|
| 51 | u32			fc_flow; | 
|---|
| 52 | u32			fc_nlflags; | 
|---|
| 53 | struct nl_info		fc_nlinfo; | 
|---|
| 54 | struct nlattr		*fc_encap; | 
|---|
| 55 | u16			fc_encap_type; | 
|---|
| 56 | }; | 
|---|
| 57 |  | 
|---|
| 58 | struct fib_info; | 
|---|
| 59 | struct rtable; | 
|---|
| 60 |  | 
|---|
| 61 | struct fib_nh_exception { | 
|---|
| 62 | struct fib_nh_exception __rcu	*fnhe_next; | 
|---|
| 63 | int				fnhe_genid; | 
|---|
| 64 | __be32				fnhe_daddr; | 
|---|
| 65 | u32				fnhe_pmtu; | 
|---|
| 66 | bool				fnhe_mtu_locked; | 
|---|
| 67 | __be32				fnhe_gw; | 
|---|
| 68 | unsigned long			fnhe_expires; | 
|---|
| 69 | struct rtable __rcu		*fnhe_rth_input; | 
|---|
| 70 | struct rtable __rcu		*fnhe_rth_output; | 
|---|
| 71 | unsigned long			fnhe_stamp; | 
|---|
| 72 | struct rcu_head			rcu; | 
|---|
| 73 | }; | 
|---|
| 74 |  | 
|---|
| 75 | struct fnhe_hash_bucket { | 
|---|
| 76 | struct fib_nh_exception __rcu	*chain; | 
|---|
| 77 | }; | 
|---|
| 78 |  | 
|---|
| 79 | #define FNHE_HASH_SHIFT		11 | 
|---|
| 80 | #define FNHE_HASH_SIZE		(1 << FNHE_HASH_SHIFT) | 
|---|
| 81 | #define FNHE_RECLAIM_DEPTH	5 | 
|---|
| 82 |  | 
|---|
| 83 | struct fib_nh_common { | 
|---|
| 84 | struct net_device	*nhc_dev; | 
|---|
| 85 | netdevice_tracker	nhc_dev_tracker; | 
|---|
| 86 | int			nhc_oif; | 
|---|
| 87 | unsigned char		nhc_scope; | 
|---|
| 88 | u8			nhc_family; | 
|---|
| 89 | u8			nhc_gw_family; | 
|---|
| 90 | unsigned char		nhc_flags; | 
|---|
| 91 | struct lwtunnel_state	*nhc_lwtstate; | 
|---|
| 92 |  | 
|---|
| 93 | union { | 
|---|
| 94 | __be32          ipv4; | 
|---|
| 95 | struct in6_addr ipv6; | 
|---|
| 96 | } nhc_gw; | 
|---|
| 97 |  | 
|---|
| 98 | int			nhc_weight; | 
|---|
| 99 | atomic_t		nhc_upper_bound; | 
|---|
| 100 |  | 
|---|
| 101 | /* v4 specific, but allows fib6_nh with v4 routes */ | 
|---|
| 102 | struct rtable __rcu * __percpu *nhc_pcpu_rth_output; | 
|---|
| 103 | struct rtable __rcu     *nhc_rth_input; | 
|---|
| 104 | struct fnhe_hash_bucket	__rcu *nhc_exceptions; | 
|---|
| 105 | }; | 
|---|
| 106 |  | 
|---|
| 107 | struct fib_nh { | 
|---|
| 108 | struct fib_nh_common	nh_common; | 
|---|
| 109 | struct hlist_node	nh_hash; | 
|---|
| 110 | struct fib_info		*nh_parent; | 
|---|
| 111 | #ifdef CONFIG_IP_ROUTE_CLASSID | 
|---|
| 112 | __u32			nh_tclassid; | 
|---|
| 113 | #endif | 
|---|
| 114 | __be32			nh_saddr; | 
|---|
| 115 | int			nh_saddr_genid; | 
|---|
| 116 | #define fib_nh_family		nh_common.nhc_family | 
|---|
| 117 | #define fib_nh_dev		nh_common.nhc_dev | 
|---|
| 118 | #define fib_nh_dev_tracker	nh_common.nhc_dev_tracker | 
|---|
| 119 | #define fib_nh_oif		nh_common.nhc_oif | 
|---|
| 120 | #define fib_nh_flags		nh_common.nhc_flags | 
|---|
| 121 | #define fib_nh_lws		nh_common.nhc_lwtstate | 
|---|
| 122 | #define fib_nh_scope		nh_common.nhc_scope | 
|---|
| 123 | #define fib_nh_gw_family	nh_common.nhc_gw_family | 
|---|
| 124 | #define fib_nh_gw4		nh_common.nhc_gw.ipv4 | 
|---|
| 125 | #define fib_nh_gw6		nh_common.nhc_gw.ipv6 | 
|---|
| 126 | #define fib_nh_weight		nh_common.nhc_weight | 
|---|
| 127 | #define fib_nh_upper_bound	nh_common.nhc_upper_bound | 
|---|
| 128 | }; | 
|---|
| 129 |  | 
|---|
| 130 | /* | 
|---|
| 131 | * This structure contains data shared by many of routes. | 
|---|
| 132 | */ | 
|---|
| 133 |  | 
|---|
| 134 | struct nexthop; | 
|---|
| 135 |  | 
|---|
| 136 | struct fib_info { | 
|---|
| 137 | struct hlist_node	fib_hash; | 
|---|
| 138 | struct hlist_node	fib_lhash; | 
|---|
| 139 | struct list_head	nh_list; | 
|---|
| 140 | struct net		*fib_net; | 
|---|
| 141 | refcount_t		fib_treeref; | 
|---|
| 142 | refcount_t		fib_clntref; | 
|---|
| 143 | unsigned int		fib_flags; | 
|---|
| 144 | unsigned char		fib_dead; | 
|---|
| 145 | unsigned char		fib_protocol; | 
|---|
| 146 | unsigned char		fib_scope; | 
|---|
| 147 | unsigned char		fib_type; | 
|---|
| 148 | __be32			fib_prefsrc; | 
|---|
| 149 | u32			fib_tb_id; | 
|---|
| 150 | u32			fib_priority; | 
|---|
| 151 | struct dst_metrics	*fib_metrics; | 
|---|
| 152 | #define fib_mtu fib_metrics->metrics[RTAX_MTU-1] | 
|---|
| 153 | #define fib_window fib_metrics->metrics[RTAX_WINDOW-1] | 
|---|
| 154 | #define fib_rtt fib_metrics->metrics[RTAX_RTT-1] | 
|---|
| 155 | #define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1] | 
|---|
| 156 | int			fib_nhs; | 
|---|
| 157 | bool			fib_nh_is_v6; | 
|---|
| 158 | bool			nh_updated; | 
|---|
| 159 | bool			pfsrc_removed; | 
|---|
| 160 | struct nexthop		*nh; | 
|---|
| 161 | struct rcu_head		rcu; | 
|---|
| 162 | struct fib_nh		fib_nh[] __counted_by(fib_nhs); | 
|---|
| 163 | }; | 
|---|
| 164 |  | 
|---|
| 165 | int __net_init fib4_semantics_init(struct net *net); | 
|---|
| 166 | void __net_exit fib4_semantics_exit(struct net *net); | 
|---|
| 167 |  | 
|---|
| 168 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 
|---|
| 169 | struct fib_rule; | 
|---|
| 170 | #endif | 
|---|
| 171 |  | 
|---|
| 172 | struct fib_table; | 
|---|
| 173 | struct fib_result { | 
|---|
| 174 | __be32			prefix; | 
|---|
| 175 | unsigned char		prefixlen; | 
|---|
| 176 | unsigned char		nh_sel; | 
|---|
| 177 | unsigned char		type; | 
|---|
| 178 | unsigned char		scope; | 
|---|
| 179 | u32			tclassid; | 
|---|
| 180 | dscp_t			dscp; | 
|---|
| 181 | struct fib_nh_common	*nhc; | 
|---|
| 182 | struct fib_info		*fi; | 
|---|
| 183 | struct fib_table	*table; | 
|---|
| 184 | struct hlist_head	*fa_head; | 
|---|
| 185 | }; | 
|---|
| 186 |  | 
|---|
| 187 | struct fib_result_nl { | 
|---|
| 188 | __be32		fl_addr;   /* To be looked up*/ | 
|---|
| 189 | u32		fl_mark; | 
|---|
| 190 | unsigned char	fl_tos; | 
|---|
| 191 | unsigned char   fl_scope; | 
|---|
| 192 | unsigned char   tb_id_in; | 
|---|
| 193 |  | 
|---|
| 194 | unsigned char   tb_id;      /* Results */ | 
|---|
| 195 | unsigned char	prefixlen; | 
|---|
| 196 | unsigned char	nh_sel; | 
|---|
| 197 | unsigned char	type; | 
|---|
| 198 | unsigned char	scope; | 
|---|
| 199 | int             err; | 
|---|
| 200 | }; | 
|---|
| 201 |  | 
|---|
| 202 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 
|---|
| 203 | #define FIB_TABLE_HASHSZ 256 | 
|---|
| 204 | #else | 
|---|
| 205 | #define FIB_TABLE_HASHSZ 2 | 
|---|
| 206 | #endif | 
|---|
| 207 |  | 
|---|
| 208 | __be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc, | 
|---|
| 209 | unsigned char scope); | 
|---|
| 210 | __be32 fib_result_prefsrc(struct net *net, struct fib_result *res); | 
|---|
| 211 |  | 
|---|
| 212 | #define FIB_RES_NHC(res)		((res).nhc) | 
|---|
| 213 | #define FIB_RES_DEV(res)	(FIB_RES_NHC(res)->nhc_dev) | 
|---|
| 214 | #define FIB_RES_OIF(res)	(FIB_RES_NHC(res)->nhc_oif) | 
|---|
| 215 |  | 
|---|
| 216 | struct fib_rt_info { | 
|---|
| 217 | struct fib_info		*fi; | 
|---|
| 218 | u32			tb_id; | 
|---|
| 219 | __be32			dst; | 
|---|
| 220 | int			dst_len; | 
|---|
| 221 | dscp_t			dscp; | 
|---|
| 222 | u8			type; | 
|---|
| 223 | u8			offload:1, | 
|---|
| 224 | trap:1, | 
|---|
| 225 | offload_failed:1, | 
|---|
| 226 | unused:5; | 
|---|
| 227 | }; | 
|---|
| 228 |  | 
|---|
| 229 | struct fib_entry_notifier_info { | 
|---|
| 230 | struct fib_notifier_info info; /* must be first */ | 
|---|
| 231 | u32 dst; | 
|---|
| 232 | int dst_len; | 
|---|
| 233 | struct fib_info *fi; | 
|---|
| 234 | dscp_t dscp; | 
|---|
| 235 | u8 type; | 
|---|
| 236 | u32 tb_id; | 
|---|
| 237 | }; | 
|---|
| 238 |  | 
|---|
| 239 | struct fib_nh_notifier_info { | 
|---|
| 240 | struct fib_notifier_info info; /* must be first */ | 
|---|
| 241 | struct fib_nh *fib_nh; | 
|---|
| 242 | }; | 
|---|
| 243 |  | 
|---|
| 244 | int call_fib4_notifier(struct notifier_block *nb, | 
|---|
| 245 | enum fib_event_type event_type, | 
|---|
| 246 | struct fib_notifier_info *info); | 
|---|
| 247 | int call_fib4_notifiers(struct net *net, enum fib_event_type event_type, | 
|---|
| 248 | struct fib_notifier_info *info); | 
|---|
| 249 |  | 
|---|
| 250 | int __net_init fib4_notifier_init(struct net *net); | 
|---|
| 251 | void __net_exit fib4_notifier_exit(struct net *net); | 
|---|
| 252 |  | 
|---|
| 253 | void fib_info_notify_update(struct net *net, struct nl_info *info); | 
|---|
| 254 | int fib_notify(struct net *net, struct notifier_block *nb, | 
|---|
| 255 | struct netlink_ext_ack *extack); | 
|---|
| 256 |  | 
|---|
| 257 | struct fib_table { | 
|---|
| 258 | struct hlist_node	tb_hlist; | 
|---|
| 259 | u32			tb_id; | 
|---|
| 260 | int			tb_num_default; | 
|---|
| 261 | struct rcu_head		rcu; | 
|---|
| 262 | unsigned long 		*tb_data; | 
|---|
| 263 | unsigned long		__data[]; | 
|---|
| 264 | }; | 
|---|
| 265 |  | 
|---|
| 266 | struct fib_dump_filter { | 
|---|
| 267 | u32			table_id; | 
|---|
| 268 | /* filter_set is an optimization that an entry is set */ | 
|---|
| 269 | bool			filter_set; | 
|---|
| 270 | bool			dump_routes; | 
|---|
| 271 | bool			dump_exceptions; | 
|---|
| 272 | bool			rtnl_held; | 
|---|
| 273 | unsigned char		protocol; | 
|---|
| 274 | unsigned char		rt_type; | 
|---|
| 275 | unsigned int		flags; | 
|---|
| 276 | struct net_device	*dev; | 
|---|
| 277 | }; | 
|---|
| 278 |  | 
|---|
| 279 | int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, | 
|---|
| 280 | struct fib_result *res, int fib_flags); | 
|---|
| 281 | int fib_table_insert(struct net *, struct fib_table *, struct fib_config *, | 
|---|
| 282 | struct netlink_ext_ack *extack); | 
|---|
| 283 | int fib_table_delete(struct net *, struct fib_table *, struct fib_config *, | 
|---|
| 284 | struct netlink_ext_ack *extack); | 
|---|
| 285 | int fib_table_dump(struct fib_table *table, struct sk_buff *skb, | 
|---|
| 286 | struct netlink_callback *cb, struct fib_dump_filter *filter); | 
|---|
| 287 | int fib_table_flush(struct net *net, struct fib_table *table, bool flush_all); | 
|---|
| 288 | struct fib_table *fib_trie_unmerge(struct fib_table *main_tb); | 
|---|
| 289 | void fib_table_flush_external(struct fib_table *table); | 
|---|
| 290 | void fib_free_table(struct fib_table *tb); | 
|---|
| 291 |  | 
|---|
| 292 | #ifndef CONFIG_IP_MULTIPLE_TABLES | 
|---|
| 293 |  | 
|---|
| 294 | #define TABLE_LOCAL_INDEX	(RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1)) | 
|---|
| 295 | #define TABLE_MAIN_INDEX	(RT_TABLE_MAIN  & (FIB_TABLE_HASHSZ - 1)) | 
|---|
| 296 |  | 
|---|
| 297 | static inline struct fib_table *fib_get_table(struct net *net, u32 id) | 
|---|
| 298 | { | 
|---|
| 299 | struct hlist_node *tb_hlist; | 
|---|
| 300 | struct hlist_head *ptr; | 
|---|
| 301 |  | 
|---|
| 302 | ptr = id == RT_TABLE_LOCAL ? | 
|---|
| 303 | &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] : | 
|---|
| 304 | &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]; | 
|---|
| 305 |  | 
|---|
| 306 | tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr)); | 
|---|
| 307 |  | 
|---|
| 308 | return hlist_entry(tb_hlist, struct fib_table, tb_hlist); | 
|---|
| 309 | } | 
|---|
| 310 |  | 
|---|
| 311 | static inline struct fib_table *fib_new_table(struct net *net, u32 id) | 
|---|
| 312 | { | 
|---|
| 313 | return fib_get_table(net, id); | 
|---|
| 314 | } | 
|---|
| 315 |  | 
|---|
| 316 | static inline int fib_lookup(struct net *net, const struct flowi4 *flp, | 
|---|
| 317 | struct fib_result *res, unsigned int flags) | 
|---|
| 318 | { | 
|---|
| 319 | struct fib_table *tb; | 
|---|
| 320 | int err = -ENETUNREACH; | 
|---|
| 321 |  | 
|---|
| 322 | rcu_read_lock(); | 
|---|
| 323 |  | 
|---|
| 324 | tb = fib_get_table(net, RT_TABLE_MAIN); | 
|---|
| 325 | if (tb) | 
|---|
| 326 | err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF); | 
|---|
| 327 |  | 
|---|
| 328 | if (err == -EAGAIN) | 
|---|
| 329 | err = -ENETUNREACH; | 
|---|
| 330 |  | 
|---|
| 331 | rcu_read_unlock(); | 
|---|
| 332 |  | 
|---|
| 333 | return err; | 
|---|
| 334 | } | 
|---|
| 335 |  | 
|---|
| 336 | static inline bool fib4_has_custom_rules(const struct net *net) | 
|---|
| 337 | { | 
|---|
| 338 | return false; | 
|---|
| 339 | } | 
|---|
| 340 |  | 
|---|
| 341 | static inline bool fib4_rule_default(const struct fib_rule *rule) | 
|---|
| 342 | { | 
|---|
| 343 | return true; | 
|---|
| 344 | } | 
|---|
| 345 |  | 
|---|
| 346 | static inline int fib4_rules_dump(struct net *net, struct notifier_block *nb, | 
|---|
| 347 | struct netlink_ext_ack *extack) | 
|---|
| 348 | { | 
|---|
| 349 | return 0; | 
|---|
| 350 | } | 
|---|
| 351 |  | 
|---|
| 352 | static inline unsigned int fib4_rules_seq_read(const struct net *net) | 
|---|
| 353 | { | 
|---|
| 354 | return 0; | 
|---|
| 355 | } | 
|---|
| 356 |  | 
|---|
| 357 | static inline bool fib4_rules_early_flow_dissect(struct net *net, | 
|---|
| 358 | struct sk_buff *skb, | 
|---|
| 359 | struct flowi4 *fl4, | 
|---|
| 360 | struct flow_keys *flkeys) | 
|---|
| 361 | { | 
|---|
| 362 | return false; | 
|---|
| 363 | } | 
|---|
| 364 | #else /* CONFIG_IP_MULTIPLE_TABLES */ | 
|---|
| 365 | int __net_init fib4_rules_init(struct net *net); | 
|---|
| 366 | void __net_exit fib4_rules_exit(struct net *net); | 
|---|
| 367 |  | 
|---|
| 368 | struct fib_table *fib_new_table(struct net *net, u32 id); | 
|---|
| 369 | struct fib_table *fib_get_table(struct net *net, u32 id); | 
|---|
| 370 |  | 
|---|
| 371 | int __fib_lookup(struct net *net, struct flowi4 *flp, | 
|---|
| 372 | struct fib_result *res, unsigned int flags); | 
|---|
| 373 |  | 
|---|
| 374 | static inline int fib_lookup(struct net *net, struct flowi4 *flp, | 
|---|
| 375 | struct fib_result *res, unsigned int flags) | 
|---|
| 376 | { | 
|---|
| 377 | struct fib_table *tb; | 
|---|
| 378 | int err = -ENETUNREACH; | 
|---|
| 379 |  | 
|---|
| 380 | flags |= FIB_LOOKUP_NOREF; | 
|---|
| 381 | if (net->ipv4.fib_has_custom_rules) | 
|---|
| 382 | return __fib_lookup(net, flp, res, flags); | 
|---|
| 383 |  | 
|---|
| 384 | rcu_read_lock(); | 
|---|
| 385 |  | 
|---|
| 386 | res->tclassid = 0; | 
|---|
| 387 |  | 
|---|
| 388 | tb = rcu_dereference_rtnl(net->ipv4.fib_main); | 
|---|
| 389 | if (tb) | 
|---|
| 390 | err = fib_table_lookup(tb, flp, res, fib_flags: flags); | 
|---|
| 391 |  | 
|---|
| 392 | if (!err) | 
|---|
| 393 | goto out; | 
|---|
| 394 |  | 
|---|
| 395 | tb = rcu_dereference_rtnl(net->ipv4.fib_default); | 
|---|
| 396 | if (tb) | 
|---|
| 397 | err = fib_table_lookup(tb, flp, res, fib_flags: flags); | 
|---|
| 398 |  | 
|---|
| 399 | out: | 
|---|
| 400 | if (err == -EAGAIN) | 
|---|
| 401 | err = -ENETUNREACH; | 
|---|
| 402 |  | 
|---|
| 403 | rcu_read_unlock(); | 
|---|
| 404 |  | 
|---|
| 405 | return err; | 
|---|
| 406 | } | 
|---|
| 407 |  | 
|---|
| 408 | static inline bool fib4_has_custom_rules(const struct net *net) | 
|---|
| 409 | { | 
|---|
| 410 | return net->ipv4.fib_has_custom_rules; | 
|---|
| 411 | } | 
|---|
| 412 |  | 
|---|
| 413 | bool fib4_rule_default(const struct fib_rule *rule); | 
|---|
| 414 | int fib4_rules_dump(struct net *net, struct notifier_block *nb, | 
|---|
| 415 | struct netlink_ext_ack *extack); | 
|---|
| 416 | unsigned int fib4_rules_seq_read(const struct net *net); | 
|---|
| 417 |  | 
|---|
| 418 | static inline bool fib4_rules_early_flow_dissect(struct net *net, | 
|---|
| 419 | struct sk_buff *skb, | 
|---|
| 420 | struct flowi4 *fl4, | 
|---|
| 421 | struct flow_keys *flkeys) | 
|---|
| 422 | { | 
|---|
| 423 | unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP; | 
|---|
| 424 |  | 
|---|
| 425 | if (!net->ipv4.fib_rules_require_fldissect) | 
|---|
| 426 | return false; | 
|---|
| 427 |  | 
|---|
| 428 | memset(s: flkeys, c: 0, n: sizeof(*flkeys)); | 
|---|
| 429 | __skb_flow_dissect(net, skb, flow_dissector: &flow_keys_dissector, | 
|---|
| 430 | target_container: flkeys, NULL, proto: 0, nhoff: 0, hlen: 0, flags: flag); | 
|---|
| 431 |  | 
|---|
| 432 | fl4->fl4_sport = flkeys->ports.src; | 
|---|
| 433 | fl4->fl4_dport = flkeys->ports.dst; | 
|---|
| 434 | fl4->flowi4_proto = flkeys->basic.ip_proto; | 
|---|
| 435 |  | 
|---|
| 436 | return true; | 
|---|
| 437 | } | 
|---|
| 438 |  | 
|---|
| 439 | #endif /* CONFIG_IP_MULTIPLE_TABLES */ | 
|---|
| 440 |  | 
|---|
| 441 | static inline bool fib_dscp_masked_match(dscp_t dscp, const struct flowi4 *fl4) | 
|---|
| 442 | { | 
|---|
| 443 | return dscp == (fl4->flowi4_dscp & INET_DSCP_LEGACY_TOS_MASK); | 
|---|
| 444 | } | 
|---|
| 445 |  | 
|---|
| 446 | /* Exported by fib_frontend.c */ | 
|---|
| 447 | extern const struct nla_policy rtm_ipv4_policy[]; | 
|---|
| 448 | void ip_fib_init(void); | 
|---|
| 449 | int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla, | 
|---|
| 450 | struct netlink_ext_ack *extack); | 
|---|
| 451 | __be32 fib_compute_spec_dst(struct sk_buff *skb); | 
|---|
| 452 | bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev); | 
|---|
| 453 | int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, | 
|---|
| 454 | dscp_t dscp, int oif, struct net_device *dev, | 
|---|
| 455 | struct in_device *idev, u32 *itag); | 
|---|
| 456 |  | 
|---|
| 457 | static inline enum skb_drop_reason | 
|---|
| 458 | fib_validate_source_reason(struct sk_buff *skb, __be32 src, __be32 dst, | 
|---|
| 459 | dscp_t dscp, int oif, struct net_device *dev, | 
|---|
| 460 | struct in_device *idev, u32 *itag) | 
|---|
| 461 | { | 
|---|
| 462 | int err = fib_validate_source(skb, src, dst, dscp, oif, dev, idev, | 
|---|
| 463 | itag); | 
|---|
| 464 | if (err < 0) | 
|---|
| 465 | return -err; | 
|---|
| 466 | return SKB_NOT_DROPPED_YET; | 
|---|
| 467 | } | 
|---|
| 468 |  | 
|---|
| 469 | #ifdef CONFIG_IP_ROUTE_CLASSID | 
|---|
| 470 | static inline int fib_num_tclassid_users(struct net *net) | 
|---|
| 471 | { | 
|---|
| 472 | return atomic_read(&net->ipv4.fib_num_tclassid_users); | 
|---|
| 473 | } | 
|---|
| 474 | #else | 
|---|
| 475 | static inline int fib_num_tclassid_users(struct net *net) | 
|---|
| 476 | { | 
|---|
| 477 | return 0; | 
|---|
| 478 | } | 
|---|
| 479 | #endif | 
|---|
| 480 | int fib_unmerge(struct net *net); | 
|---|
| 481 |  | 
|---|
| 482 | static inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc, | 
|---|
| 483 | const struct net_device *dev) | 
|---|
| 484 | { | 
|---|
| 485 | if (nhc->nhc_dev == dev || | 
|---|
| 486 | l3mdev_master_ifindex_rcu(dev: nhc->nhc_dev) == dev->ifindex) | 
|---|
| 487 | return true; | 
|---|
| 488 |  | 
|---|
| 489 | return false; | 
|---|
| 490 | } | 
|---|
| 491 |  | 
|---|
| 492 | /* Exported by fib_semantics.c */ | 
|---|
| 493 | int ip_fib_check_default(__be32 gw, struct net_device *dev); | 
|---|
| 494 | int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force); | 
|---|
| 495 | int fib_sync_down_addr(struct net_device *dev, __be32 local); | 
|---|
| 496 | int fib_sync_up(struct net_device *dev, unsigned char nh_flags); | 
|---|
| 497 | void fib_sync_mtu(struct net_device *dev, u32 orig_mtu); | 
|---|
| 498 | void fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig); | 
|---|
| 499 |  | 
|---|
| 500 | /* Fields used for sysctl_fib_multipath_hash_fields. | 
|---|
| 501 | * Common to IPv4 and IPv6. | 
|---|
| 502 | * | 
|---|
| 503 | * Add new fields at the end. This is user API. | 
|---|
| 504 | */ | 
|---|
| 505 | #define FIB_MULTIPATH_HASH_FIELD_SRC_IP			BIT(0) | 
|---|
| 506 | #define FIB_MULTIPATH_HASH_FIELD_DST_IP			BIT(1) | 
|---|
| 507 | #define FIB_MULTIPATH_HASH_FIELD_IP_PROTO		BIT(2) | 
|---|
| 508 | #define FIB_MULTIPATH_HASH_FIELD_FLOWLABEL		BIT(3) | 
|---|
| 509 | #define FIB_MULTIPATH_HASH_FIELD_SRC_PORT		BIT(4) | 
|---|
| 510 | #define FIB_MULTIPATH_HASH_FIELD_DST_PORT		BIT(5) | 
|---|
| 511 | #define FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP		BIT(6) | 
|---|
| 512 | #define FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP		BIT(7) | 
|---|
| 513 | #define FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO		BIT(8) | 
|---|
| 514 | #define FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL	BIT(9) | 
|---|
| 515 | #define FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT		BIT(10) | 
|---|
| 516 | #define FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT		BIT(11) | 
|---|
| 517 |  | 
|---|
| 518 | #define FIB_MULTIPATH_HASH_FIELD_OUTER_MASK		\ | 
|---|
| 519 | (FIB_MULTIPATH_HASH_FIELD_SRC_IP |		\ | 
|---|
| 520 | FIB_MULTIPATH_HASH_FIELD_DST_IP |		\ | 
|---|
| 521 | FIB_MULTIPATH_HASH_FIELD_IP_PROTO |		\ | 
|---|
| 522 | FIB_MULTIPATH_HASH_FIELD_FLOWLABEL |		\ | 
|---|
| 523 | FIB_MULTIPATH_HASH_FIELD_SRC_PORT |		\ | 
|---|
| 524 | FIB_MULTIPATH_HASH_FIELD_DST_PORT) | 
|---|
| 525 |  | 
|---|
| 526 | #define FIB_MULTIPATH_HASH_FIELD_INNER_MASK		\ | 
|---|
| 527 | (FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP |	\ | 
|---|
| 528 | FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP |	\ | 
|---|
| 529 | FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO |	\ | 
|---|
| 530 | FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL |	\ | 
|---|
| 531 | FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT |	\ | 
|---|
| 532 | FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT) | 
|---|
| 533 |  | 
|---|
| 534 | #define FIB_MULTIPATH_HASH_FIELD_ALL_MASK		\ | 
|---|
| 535 | (FIB_MULTIPATH_HASH_FIELD_OUTER_MASK |		\ | 
|---|
| 536 | FIB_MULTIPATH_HASH_FIELD_INNER_MASK) | 
|---|
| 537 |  | 
|---|
| 538 | #define FIB_MULTIPATH_HASH_FIELD_DEFAULT_MASK		\ | 
|---|
| 539 | (FIB_MULTIPATH_HASH_FIELD_SRC_IP |		\ | 
|---|
| 540 | FIB_MULTIPATH_HASH_FIELD_DST_IP |		\ | 
|---|
| 541 | FIB_MULTIPATH_HASH_FIELD_IP_PROTO) | 
|---|
| 542 |  | 
|---|
| 543 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 
|---|
| 544 | int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, | 
|---|
| 545 | const struct sk_buff *skb, struct flow_keys *flkeys); | 
|---|
| 546 |  | 
|---|
| 547 | static void | 
|---|
| 548 | fib_multipath_hash_construct_key(siphash_key_t *key, u32 mp_seed) | 
|---|
| 549 | { | 
|---|
| 550 | u64 mp_seed_64 = mp_seed; | 
|---|
| 551 |  | 
|---|
| 552 | key->key[0] = (mp_seed_64 << 32) | mp_seed_64; | 
|---|
| 553 | key->key[1] = key->key[0]; | 
|---|
| 554 | } | 
|---|
| 555 |  | 
|---|
| 556 | static inline u32 fib_multipath_hash_from_keys(const struct net *net, | 
|---|
| 557 | struct flow_keys *keys) | 
|---|
| 558 | { | 
|---|
| 559 | siphash_aligned_key_t hash_key; | 
|---|
| 560 | u32 mp_seed; | 
|---|
| 561 |  | 
|---|
| 562 | mp_seed = READ_ONCE(net->ipv4.sysctl_fib_multipath_hash_seed).mp_seed; | 
|---|
| 563 | fib_multipath_hash_construct_key(key: &hash_key, mp_seed); | 
|---|
| 564 |  | 
|---|
| 565 | return flow_hash_from_keys_seed(keys, keyval: &hash_key); | 
|---|
| 566 | } | 
|---|
| 567 | #else | 
|---|
| 568 | static inline u32 fib_multipath_hash_from_keys(const struct net *net, | 
|---|
| 569 | struct flow_keys *keys) | 
|---|
| 570 | { | 
|---|
| 571 | return flow_hash_from_keys(keys); | 
|---|
| 572 | } | 
|---|
| 573 | #endif | 
|---|
| 574 |  | 
|---|
| 575 | int fib_check_nh(struct net *net, struct fib_nh *nh, u32 table, u8 scope, | 
|---|
| 576 | struct netlink_ext_ack *extack); | 
|---|
| 577 | void fib_select_multipath(struct fib_result *res, int hash, | 
|---|
| 578 | const struct flowi4 *fl4); | 
|---|
| 579 | void fib_select_path(struct net *net, struct fib_result *res, | 
|---|
| 580 | struct flowi4 *fl4, const struct sk_buff *skb); | 
|---|
| 581 |  | 
|---|
| 582 | int fib_nh_init(struct net *net, struct fib_nh *fib_nh, | 
|---|
| 583 | struct fib_config *cfg, int nh_weight, | 
|---|
| 584 | struct netlink_ext_ack *extack); | 
|---|
| 585 | void fib_nh_release(struct net *net, struct fib_nh *fib_nh); | 
|---|
| 586 | int fib_nh_common_init(struct net *net, struct fib_nh_common *nhc, | 
|---|
| 587 | struct nlattr *fc_encap, u16 fc_encap_type, | 
|---|
| 588 | void *cfg, gfp_t gfp_flags, | 
|---|
| 589 | struct netlink_ext_ack *extack); | 
|---|
| 590 | void fib_nh_common_release(struct fib_nh_common *nhc); | 
|---|
| 591 |  | 
|---|
| 592 | /* Exported by fib_trie.c */ | 
|---|
| 593 | void fib_alias_hw_flags_set(struct net *net, const struct fib_rt_info *fri); | 
|---|
| 594 | void fib_trie_init(void); | 
|---|
| 595 | struct fib_table *fib_trie_table(u32 id, struct fib_table *alias); | 
|---|
| 596 | bool fib_lookup_good_nhc(const struct fib_nh_common *nhc, int fib_flags, | 
|---|
| 597 | const struct flowi4 *flp); | 
|---|
| 598 |  | 
|---|
| 599 | static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) | 
|---|
| 600 | { | 
|---|
| 601 | #ifdef CONFIG_IP_ROUTE_CLASSID | 
|---|
| 602 | struct fib_nh_common *nhc = res->nhc; | 
|---|
| 603 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 
|---|
| 604 | u32 rtag; | 
|---|
| 605 | #endif | 
|---|
| 606 | if (nhc->nhc_family == AF_INET) { | 
|---|
| 607 | struct fib_nh *nh; | 
|---|
| 608 |  | 
|---|
| 609 | nh = container_of(nhc, struct fib_nh, nh_common); | 
|---|
| 610 | *itag = nh->nh_tclassid << 16; | 
|---|
| 611 | } else { | 
|---|
| 612 | *itag = 0; | 
|---|
| 613 | } | 
|---|
| 614 |  | 
|---|
| 615 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 
|---|
| 616 | rtag = res->tclassid; | 
|---|
| 617 | if (*itag == 0) | 
|---|
| 618 | *itag = (rtag<<16); | 
|---|
| 619 | *itag |= (rtag>>16); | 
|---|
| 620 | #endif | 
|---|
| 621 | #endif | 
|---|
| 622 | } | 
|---|
| 623 |  | 
|---|
| 624 | void fib_flush(struct net *net); | 
|---|
| 625 | void free_fib_info(struct fib_info *fi); | 
|---|
| 626 |  | 
|---|
| 627 | static inline void fib_info_hold(struct fib_info *fi) | 
|---|
| 628 | { | 
|---|
| 629 | refcount_inc(r: &fi->fib_clntref); | 
|---|
| 630 | } | 
|---|
| 631 |  | 
|---|
| 632 | static inline void fib_info_put(struct fib_info *fi) | 
|---|
| 633 | { | 
|---|
| 634 | if (refcount_dec_and_test(r: &fi->fib_clntref)) | 
|---|
| 635 | free_fib_info(fi); | 
|---|
| 636 | } | 
|---|
| 637 |  | 
|---|
| 638 | #ifdef CONFIG_PROC_FS | 
|---|
| 639 | int __net_init fib_proc_init(struct net *net); | 
|---|
| 640 | void __net_exit fib_proc_exit(struct net *net); | 
|---|
| 641 | #else | 
|---|
| 642 | static inline int fib_proc_init(struct net *net) | 
|---|
| 643 | { | 
|---|
| 644 | return 0; | 
|---|
| 645 | } | 
|---|
| 646 | static inline void fib_proc_exit(struct net *net) | 
|---|
| 647 | { | 
|---|
| 648 | } | 
|---|
| 649 | #endif | 
|---|
| 650 |  | 
|---|
| 651 | u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr); | 
|---|
| 652 |  | 
|---|
| 653 | int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, | 
|---|
| 654 | struct fib_dump_filter *filter, | 
|---|
| 655 | struct netlink_callback *cb); | 
|---|
| 656 |  | 
|---|
| 657 | int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh, | 
|---|
| 658 | u8 rt_family, unsigned char *flags, bool skip_oif); | 
|---|
| 659 | int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh, | 
|---|
| 660 | int nh_weight, u8 rt_family, u32 nh_tclassid); | 
|---|
| 661 | #endif  /* _NET_FIB_H */ | 
|---|
| 662 |  | 
|---|