History

bpf: Add netns cookie and enable it for bpf cgroup hooks

In Cilium we're mainly using BPF cgroup hooks today in order to implement kube-proxy free Kubernetes service translation for ClusterIP, NodePort (*), ExternalIP, and LoadBalancer as well as HostPort mapping [0] for all traffic between Cilium managed nodes. While this works in its current shape and avoids packet-level NAT for inter Cilium managed node traffic, there is one major limitation we're facing today, that is, lack of netns awareness. In Kubernetes, the concept of Pods (which hold one or multiple containers) has been built around network namespaces, so while we can use the global scope of attaching to root BPF cgroup hooks also to our advantage (e.g. for exposing NodePort ports on loopback addresses), we also have the need to differentiate between initial network namespaces and non-initial one. For example, ExternalIP services mandate that non-local service IPs are not to be translated from the host (initial) network namespace as one example. Right now, we have an ugly work-around in place where non-local service IPs for ExternalIP services are not xlated from connect() and friends BPF hooks but instead via less efficient packet-level NAT on the veth tc ingress hook for Pod traffic. On top of determining whether we're in initial or non-initial network namespace we also have a need for a socket-cookie like mechanism for network namespaces scope. Socket cookies have the nice property that they can be combined as part of the key structure e.g. for BPF LRU maps without having to worry that the cookie could be recycled. We are planning to use this for our sessionAffinity implementation for services. Therefore, add a new bpf_get_netns_cookie() helper which would resolve both use cases at once: bpf_get_netns_cookie(NULL) would provide the cookie for the initial network namespace while passing the context instead of NULL would provide the cookie from the application's network namespace. We're using a hole, so no size increase; the assignment happens only once. Therefore this allows for a comparison on initial namespace as well as regular cookie usage as we have today with socket cookies. We could later on enable this helper for other program types as well as we would see need. (*) Both externalTrafficPolicy={Local|Cluster} types [0] https://github.com/cilium/cilium/blob/master/bpf/bpf_sock.c

Daniel Borkmann committed 6 years ago

Commit f3189031 parent fcf752e7 files · +103 −8Browse files

Showing the changes to include/uapi (1 of 7 files). Show all

Unified · Split

include/uapi/linux/bpf.h+15−1
@@ -2950,6 +2950,19 @@ union bpf_attr { · 2949 unmodified lines
2950 * restricted to raw_tracepoint bpf programs.2950 * restricted to raw_tracepoint bpf programs.
2951 * Return2951 * Return
2952 * 0 on success, or a negative error in case of failure.2952 * 0 on success, or a negative error in case of failure.
2953 *
2954 * u64 bpf_get_netns_cookie(void *ctx)
2955 * Description
2956 * Retrieve the cookie (generated by the kernel) of the network
2957 * namespace the input *ctx* is associated with. The network
2958 * namespace cookie remains stable for its lifetime and provides
2959 * a global identifier that can be assumed unique. If *ctx* is
2960 * NULL, then the helper returns the cookie for the initial
2961 * network namespace. The cookie itself is very similar to that
2962 * of bpf_get_socket_cookie() helper, but for network namespaces
2963 * instead of sockets.
2964 * Return
2965 * A 8-byte long opaque number.
2953 */2966 */
2954#define __BPF_FUNC_MAPPER(FN) \2967#define __BPF_FUNC_MAPPER(FN) \
2955 FN(unspec), \2968 FN(unspec), \
@@ -3073,7 +3086,8 @@ union bpf_attr { · 117 unmodified lines
3073 FN(jiffies64), \3086 FN(jiffies64), \
3074 FN(read_branch_records), \3087 FN(read_branch_records), \
3075 FN(get_ns_current_pid_tgid), \3088 FN(get_ns_current_pid_tgid), \
3076 FN(xdp_output),3089 FN(xdp_output), \
3090 FN(get_netns_cookie),
3077 3091
3078/* integer value in 'imm' field of BPF_CALL instruction selects which helper3092/* integer value in 'imm' field of BPF_CALL instruction selects which helper
3079 * function eBPF program intends to call3093 * function eBPF program intends to call