Skip to content

Commit ff1f56d

Browse files
committed
Merge branch 'bpf-fib-lookup-helper'
David Ahern says: ==================== Provide a helper for doing a FIB and neighbor lookup in the kernel tables from an XDP program. The helper provides a fastpath for forwarding packets. If the packet is a local delivery or for any reason is not a simple lookup and forward, the packet is expected to continue up the stack for full processing. The response from a FIB and neighbor lookup is either the egress index with the bpf_fib_lookup struct filled in with dmac and gateway or 0 meaning the packet should continue up the stack. In time we can revisit this to return the FIB lookup result errno if it is one of the special RTN_'s such as RTN_BLACKHOLE (-EINVAL) so that the XDP programs can do an early drop if desired. Patches 1-6 do some more refactoring to IPv6 with the end goal of extracting a FIB lookup function that aligns with fib_lookup for IPv4, basically returning a fib6_info without creating a dst based entry. Patch 7 adds lookup functions to the ipv6 stub. These are needed since bpf is built into the kernel and ipv6 may not be built or loaded. Patch 8 adds the bpf helper and 9 adds a sample program. v3 - remove ETH_ALEN and in6_addr from uapi header v2 - removed pkt_access from bpf_func_proto as noticed by Daniel - added check in that IPv6 forwarding is enabled - added DaveM's ack on patches 1-7 and 9 based on v1 response and fact that no changes were made to them in v2 v1 - updated commit messages and cover letter - added comment to sample program noting lack of verification on egress device supporting XDP RFC v2 - fixed use of foward helper from cls_act as noted by Daniel - in patch 1 rename fib6_lookup_1 as well for consistency ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2 parents 68625b7 + fe61605 commit ff1f56d

File tree

14 files changed

+854
-75
lines changed

14 files changed

+854
-75
lines changed

include/net/addrconf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,20 @@ struct ipv6_stub {
223223
const struct in6_addr *addr);
224224
int (*ipv6_dst_lookup)(struct net *net, struct sock *sk,
225225
struct dst_entry **dst, struct flowi6 *fl6);
226+
227+
struct fib6_table *(*fib6_get_table)(struct net *net, u32 id);
228+
struct fib6_info *(*fib6_lookup)(struct net *net, int oif,
229+
struct flowi6 *fl6, int flags);
230+
struct fib6_info *(*fib6_table_lookup)(struct net *net,
231+
struct fib6_table *table,
232+
int oif, struct flowi6 *fl6,
233+
int flags);
234+
struct fib6_info *(*fib6_multipath_select)(const struct net *net,
235+
struct fib6_info *f6i,
236+
struct flowi6 *fl6, int oif,
237+
const struct sk_buff *skb,
238+
int strict);
239+
226240
void (*udpv6_encap_enable)(void);
227241
void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
228242
const struct in6_addr *solicited_addr,

include/net/ip6_fib.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,24 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
376376
const struct sk_buff *skb,
377377
int flags, pol_lookup_t lookup);
378378

379-
struct fib6_node *fib6_lookup(struct fib6_node *root,
380-
const struct in6_addr *daddr,
381-
const struct in6_addr *saddr);
379+
/* called with rcu lock held; can return error pointer
380+
* caller needs to select path
381+
*/
382+
struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
383+
int flags);
384+
385+
/* called with rcu lock held; caller needs to select path */
386+
struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
387+
int oif, struct flowi6 *fl6, int strict);
388+
389+
struct fib6_info *fib6_multipath_select(const struct net *net,
390+
struct fib6_info *match,
391+
struct flowi6 *fl6, int oif,
392+
const struct sk_buff *skb, int strict);
393+
394+
struct fib6_node *fib6_node_lookup(struct fib6_node *root,
395+
const struct in6_addr *daddr,
396+
const struct in6_addr *saddr);
382397

383398
struct fib6_node *fib6_locate(struct fib6_node *root,
384399
const struct in6_addr *daddr, int dst_len,

include/trace/events/fib6.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212

1313
TRACE_EVENT(fib6_table_lookup,
1414

15-
TP_PROTO(const struct net *net, const struct rt6_info *rt,
15+
TP_PROTO(const struct net *net, const struct fib6_info *f6i,
1616
struct fib6_table *table, const struct flowi6 *flp),
1717

18-
TP_ARGS(net, rt, table, flp),
18+
TP_ARGS(net, f6i, table, flp),
1919

2020
TP_STRUCT__entry(
2121
__field( u32, tb_id )
@@ -48,20 +48,20 @@ TRACE_EVENT(fib6_table_lookup,
4848
in6 = (struct in6_addr *)__entry->dst;
4949
*in6 = flp->daddr;
5050

51-
if (rt->rt6i_idev) {
52-
__assign_str(name, rt->rt6i_idev->dev->name);
51+
if (f6i->fib6_nh.nh_dev) {
52+
__assign_str(name, f6i->fib6_nh.nh_dev);
5353
} else {
5454
__assign_str(name, "");
5555
}
56-
if (rt == net->ipv6.ip6_null_entry) {
56+
if (f6i == net->ipv6.fib6_null_entry) {
5757
struct in6_addr in6_zero = {};
5858

5959
in6 = (struct in6_addr *)__entry->gw;
6060
*in6 = in6_zero;
6161

62-
} else if (rt) {
62+
} else if (f6i) {
6363
in6 = (struct in6_addr *)__entry->gw;
64-
*in6 = rt->rt6i_gateway;
64+
*in6 = f6i->fib6_nh.nh_gw;
6565
}
6666
),
6767

include/uapi/linux/bpf.h

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1828,6 +1828,33 @@ union bpf_attr {
18281828
* Return
18291829
* 0 on success, or a negative error in case of failure.
18301830
*
1831+
*
1832+
* int bpf_fib_lookup(void *ctx, struct bpf_fib_lookup *params, int plen, u32 flags)
1833+
* Description
1834+
* Do FIB lookup in kernel tables using parameters in *params*.
1835+
* If lookup is successful and result shows packet is to be
1836+
* forwarded, the neighbor tables are searched for the nexthop.
1837+
* If successful (ie., FIB lookup shows forwarding and nexthop
1838+
* is resolved), the nexthop address is returned in ipv4_dst,
1839+
* ipv6_dst or mpls_out based on family, smac is set to mac
1840+
* address of egress device, dmac is set to nexthop mac address,
1841+
* rt_metric is set to metric from route.
1842+
*
1843+
* *plen* argument is the size of the passed in struct.
1844+
* *flags* argument can be one or more BPF_FIB_LOOKUP_ flags:
1845+
*
1846+
* **BPF_FIB_LOOKUP_DIRECT** means do a direct table lookup vs
1847+
* full lookup using FIB rules
1848+
* **BPF_FIB_LOOKUP_OUTPUT** means do lookup from an egress
1849+
* perspective (default is ingress)
1850+
*
1851+
* *ctx* is either **struct xdp_md** for XDP programs or
1852+
* **struct sk_buff** tc cls_act programs.
1853+
*
1854+
* Return
1855+
* Egress device index on success, 0 if packet needs to continue
1856+
* up the stack for further processing or a negative error in case
1857+
* of failure.
18311858
*/
18321859
#define __BPF_FUNC_MAPPER(FN) \
18331860
FN(unspec), \
@@ -1898,7 +1925,8 @@ union bpf_attr {
18981925
FN(xdp_adjust_tail), \
18991926
FN(skb_get_xfrm_state), \
19001927
FN(get_stack), \
1901-
FN(skb_load_bytes_relative),
1928+
FN(skb_load_bytes_relative), \
1929+
FN(fib_lookup),
19021930

19031931
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
19041932
* function eBPF program intends to call
@@ -2321,4 +2349,55 @@ struct bpf_raw_tracepoint_args {
23212349
__u64 args[0];
23222350
};
23232351

2352+
/* DIRECT: Skip the FIB rules and go to FIB table associated with device
2353+
* OUTPUT: Do lookup from egress perspective; default is ingress
2354+
*/
2355+
#define BPF_FIB_LOOKUP_DIRECT BIT(0)
2356+
#define BPF_FIB_LOOKUP_OUTPUT BIT(1)
2357+
2358+
struct bpf_fib_lookup {
2359+
/* input */
2360+
__u8 family; /* network family, AF_INET, AF_INET6, AF_MPLS */
2361+
2362+
/* set if lookup is to consider L4 data - e.g., FIB rules */
2363+
__u8 l4_protocol;
2364+
__be16 sport;
2365+
__be16 dport;
2366+
2367+
/* total length of packet from network header - used for MTU check */
2368+
__u16 tot_len;
2369+
__u32 ifindex; /* L3 device index for lookup */
2370+
2371+
union {
2372+
/* inputs to lookup */
2373+
__u8 tos; /* AF_INET */
2374+
__be32 flowlabel; /* AF_INET6 */
2375+
2376+
/* output: metric of fib result */
2377+
__u32 rt_metric;
2378+
};
2379+
2380+
union {
2381+
__be32 mpls_in;
2382+
__be32 ipv4_src;
2383+
__u32 ipv6_src[4]; /* in6_addr; network order */
2384+
};
2385+
2386+
/* input to bpf_fib_lookup, *dst is destination address.
2387+
* output: bpf_fib_lookup sets to gateway address
2388+
*/
2389+
union {
2390+
/* return for MPLS lookups */
2391+
__be32 mpls_out[4]; /* support up to 4 labels */
2392+
__be32 ipv4_dst;
2393+
__u32 ipv6_dst[4]; /* in6_addr; network order */
2394+
};
2395+
2396+
/* output */
2397+
__be16 h_vlan_proto;
2398+
__be16 h_vlan_TCI;
2399+
__u8 smac[6]; /* ETH_ALEN */
2400+
__u8 dmac[6]; /* ETH_ALEN */
2401+
};
2402+
23242403
#endif /* _UAPI__LINUX_BPF_H__ */

0 commit comments

Comments
 (0)