Skip to content

Commit

Permalink
bpf: v6 support for NodePort via tunnel
Browse files Browse the repository at this point in the history
Adding v6 counterparts to get NodePort working via tunnel when the
backend is local and also remote.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
  • Loading branch information
borkmann committed Jul 21, 2019
1 parent fc80bb3 commit 8f52a9b
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 9 deletions.
10 changes: 10 additions & 0 deletions bpf/bpf_overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ static inline int handle_ipv6(struct __sk_buff *skb, __u32 *identity)
int l4_off, l3_off = ETH_HLEN, hdrlen;
bool decrypted;

/* verifier workaround (dereference of modified ctx ptr) */
if (!revalidate_data(skb, &data, &data_end, &ip6))
return DROP_INVALID;
#ifdef ENABLE_NODEPORT
if (!tc_index_skip_nodeport(skb)) {
int ret = nodeport_lb6(skb, *identity);
if (ret < 0)
return ret;
}
#endif
if (!revalidate_data(skb, &data, &data_end, &ip6))
return DROP_INVALID;

Expand Down
68 changes: 60 additions & 8 deletions bpf/lib/nodeport.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static inline bool __inline__ tc_index_skip_nodeport(struct __sk_buff *skb)
__section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_IPV6_NODEPORT_NAT)
int tail_nodeport_nat_ipv6(struct __sk_buff *skb)
{
int ifindex = NATIVE_DEV_IFINDEX, ret, dir = skb->cb[CB_NAT];
struct bpf_fib_lookup fib_params = {};
struct ipv6_nat_target target = {
.min_port = NODEPORT_PORT_MIN_NAT,
Expand All @@ -63,10 +64,35 @@ int tail_nodeport_nat_ipv6(struct __sk_buff *skb)
};
void *data, *data_end;
struct ipv6hdr *ip6;
int ret, dir = skb->cb[CB_NAT];

BPF_V6(target.addr, IPV6_NODEPORT);
#ifdef ENCAP_IFINDEX
if (dir == NAT_DIR_EGRESS) {
struct remote_endpoint_info *info;
union v6addr *dst;

if (!revalidate_data(skb, &data, &data_end, &ip6))
return DROP_INVALID;

dst = (union v6addr *)&ip6->daddr;
info = ipcache_lookup6(&IPCACHE_MAP, dst, V6_CACHE_KEY_LEN);
if (info != NULL && info->tunnel_endpoint != 0) {
int ret = __encap_with_nodeid(skb, info->tunnel_endpoint,
SECLABEL, TRACE_PAYLOAD_LEN);
if (ret)
return ret;

BPF_V6(target.addr, HOST_IP);
ifindex = ENCAP_IFINDEX;

/* fib lookup not necessary when going over tunnel. */
if (eth_store_daddr(skb, fib_params.dmac, 0) < 0)
return DROP_WRITE_ERROR;
if (eth_store_saddr(skb, fib_params.smac, 0) < 0)
return DROP_WRITE_ERROR;
}
}
#endif
ret = snat_v6_process(skb, dir, &target);
if (IS_ERR(ret)) {
/* In case of no mapping, recircle back to main path. SNAT is very
Expand All @@ -88,13 +114,16 @@ int tail_nodeport_nat_ipv6(struct __sk_buff *skb)
goto drop_err;
}

if (ifindex == ENCAP_IFINDEX)
goto out_send;

if (!revalidate_data(skb, &data, &data_end, &ip6)) {
ret = DROP_INVALID;
goto drop_err;
}

fib_params.family = AF_INET6;
fib_params.ifindex = NATIVE_DEV_IFINDEX;
fib_params.ifindex = ifindex;
ipv6_addr_copy((union v6addr *) &fib_params.ipv6_src, (union v6addr *) &ip6->saddr);
ipv6_addr_copy((union v6addr *) &fib_params.ipv6_dst, (union v6addr *) &ip6->daddr);

Expand All @@ -113,8 +142,8 @@ int tail_nodeport_nat_ipv6(struct __sk_buff *skb)
ret = DROP_WRITE_ERROR;
goto drop_err;
}

return redirect(fib_params.ifindex, 0);
out_send:
return redirect(ifindex, 0);
drop_err:
return send_drop_notify_error(skb, 0, ret, TC_ACT_SHOT,
dir == NAT_DIR_INGRESS ?
Expand Down Expand Up @@ -227,7 +256,7 @@ static inline int nodeport_lb6(struct __sk_buff *skb, __u32 src_identity)
}

/* See comment in tail_rev_nodeport_lb4(). */
static inline int rev_nodeport_lb6(struct __sk_buff *skb)
static inline int rev_nodeport_lb6(struct __sk_buff *skb, int *ifindex)
{
int ret, ret2, l3_off = ETH_HLEN, l4_off, hdrlen;
struct ipv6_ct_tuple tuple = {};
Expand Down Expand Up @@ -263,9 +292,32 @@ static inline int rev_nodeport_lb6(struct __sk_buff *skb)

if (!revalidate_data(skb, &data, &data_end, &ip6))
return DROP_INVALID;
#ifdef ENCAP_IFINDEX
{
union v6addr *dst = (union v6addr *)&ip6->daddr;
struct remote_endpoint_info *info;

info = ipcache_lookup6(&IPCACHE_MAP, dst, V6_CACHE_KEY_LEN);
if (info != NULL && info->tunnel_endpoint != 0) {
int ret = __encap_with_nodeid(skb, info->tunnel_endpoint,
SECLABEL, TRACE_PAYLOAD_LEN);
if (ret)
return ret;

*ifindex = ENCAP_IFINDEX;

/* fib lookup not necessary when going over tunnel. */
if (eth_store_daddr(skb, fib_params.dmac, 0) < 0)
return DROP_WRITE_ERROR;
if (eth_store_saddr(skb, fib_params.smac, 0) < 0)
return DROP_WRITE_ERROR;

return TC_ACT_OK;
}
}
#endif
fib_params.family = AF_INET6;
fib_params.ifindex = NATIVE_DEV_IFINDEX;
fib_params.ifindex = *ifindex;

ipv6_addr_copy((union v6addr *) &fib_params.ipv6_src, &tuple.saddr);
ipv6_addr_copy((union v6addr *) &fib_params.ipv6_dst, &tuple.daddr);
Expand All @@ -287,10 +339,10 @@ static inline int rev_nodeport_lb6(struct __sk_buff *skb)
__section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_IPV6_NODEPORT_REVNAT)
int tail_rev_nodeport_lb6(struct __sk_buff *skb)
{
int ret = rev_nodeport_lb6(skb);
int ifindex = NATIVE_DEV_IFINDEX, ret = rev_nodeport_lb6(skb, &ifindex);
if (IS_ERR(ret))
return send_drop_notify_error(skb, 0, ret, TC_ACT_SHOT, METRIC_EGRESS);
return redirect(NATIVE_DEV_IFINDEX, 0);
return redirect(ifindex, 0);
}
#endif /* ENABLE_IPV6 */

Expand Down
2 changes: 1 addition & 1 deletion daemon/bpf.sha
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
GO_BINDATA_SHA1SUM=11d2b281e44dc667ba3738f8bca64f86ae7775a0
GO_BINDATA_SHA1SUM=78f870e1cbb06ad7c5f7c2faa2877b3241d505cf
BPF_FILES=../bpf/COPYING ../bpf/Makefile ../bpf/Makefile.bpf ../bpf/bpf_alignchecker.c ../bpf/bpf_features.h ../bpf/bpf_hostdev_ingress.c ../bpf/bpf_ipsec.c ../bpf/bpf_lb.c ../bpf/bpf_lxc.c ../bpf/bpf_netdev.c ../bpf/bpf_network.c ../bpf/bpf_overlay.c ../bpf/bpf_sock.c ../bpf/bpf_xdp.c ../bpf/cilium-map-migrate.c ../bpf/filter_config.h ../bpf/include/bpf/api.h ../bpf/include/elf/elf.h ../bpf/include/elf/gelf.h ../bpf/include/elf/libelf.h ../bpf/include/iproute2/bpf_elf.h ../bpf/include/linux/bpf.h ../bpf/include/linux/bpf_common.h ../bpf/include/linux/byteorder.h ../bpf/include/linux/byteorder/big_endian.h ../bpf/include/linux/byteorder/little_endian.h ../bpf/include/linux/icmp.h ../bpf/include/linux/icmpv6.h ../bpf/include/linux/if_arp.h ../bpf/include/linux/if_ether.h ../bpf/include/linux/if_packet.h ../bpf/include/linux/in.h ../bpf/include/linux/in6.h ../bpf/include/linux/ioctl.h ../bpf/include/linux/ip.h ../bpf/include/linux/ipv6.h ../bpf/include/linux/perf_event.h ../bpf/include/linux/swab.h ../bpf/include/linux/tcp.h ../bpf/include/linux/type_mapper.h ../bpf/include/linux/udp.h ../bpf/init.sh ../bpf/lib/arp.h ../bpf/lib/common.h ../bpf/lib/config.h ../bpf/lib/conntrack.h ../bpf/lib/conntrack_map.h ../bpf/lib/csum.h ../bpf/lib/dbg.h ../bpf/lib/drop.h ../bpf/lib/encap.h ../bpf/lib/eps.h ../bpf/lib/eth.h ../bpf/lib/events.h ../bpf/lib/icmp6.h ../bpf/lib/ipv4.h ../bpf/lib/ipv6.h ../bpf/lib/l3.h ../bpf/lib/l4.h ../bpf/lib/lb.h ../bpf/lib/lxc.h ../bpf/lib/maps.h ../bpf/lib/metrics.h ../bpf/lib/nat.h ../bpf/lib/nat46.h ../bpf/lib/nodeport.h ../bpf/lib/policy.h ../bpf/lib/tailcall.h ../bpf/lib/trace.h ../bpf/lib/utils.h ../bpf/lib/xdp.h ../bpf/lxc_config.h ../bpf/netdev_config.h ../bpf/node_config.h ../bpf/probes/raw_change_tail.t ../bpf/probes/raw_fib_lookup.t ../bpf/probes/raw_insn.h ../bpf/probes/raw_invalidate_hash.t ../bpf/probes/raw_lpm_map.t ../bpf/probes/raw_lru_map.t ../bpf/probes/raw_main.c ../bpf/probes/raw_map_val_adj.t ../bpf/probes/raw_mark_map_val.t ../bpf/probes/raw_sock_cookie.t ../bpf/run_probes.sh ../bpf/sockops/Makefile ../bpf/sockops/bpf_redir.c ../bpf/sockops/bpf_sockops.c ../bpf/sockops/bpf_sockops.h ../bpf/sockops/sockops_config.h

0 comments on commit 8f52a9b

Please sign in to comment.