Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf: Refactoring egress gateway datapath #17868

Merged
merged 2 commits into from
Nov 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 2 additions & 11 deletions bpf/bpf_lxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "lib/dbg.h"
#include "lib/trace.h"
#include "lib/csum.h"
#include "lib/egress_policies.h"
#include "lib/encap.h"
#include "lib/eps.h"
#include "lib/nat.h"
Expand Down Expand Up @@ -797,17 +798,7 @@ static __always_inline int handle_ipv4_from_lxc(struct __ctx_buff *ctx,
struct egress_info *info;
struct endpoint_key key = {};

/* If tunnel endpoint is found in ipcache, it means the remote endpoint is
* in cluster. In this case, we should skip egress gateway. If destination
* is either remote node or host node, also skip egress gateway.
*/
if (tunnel_endpoint != 0 || *dst_id == REMOTE_NODE_ID || *dst_id == HOST_ID)
goto skip_egress_gateway;

/* If destination ip matches a local endpoint, we should also
* skip egress gateway.
*/
if (lookup_ip4_endpoint(ip4))
if (is_cluster_destination(ip4, *dst_id, tunnel_endpoint))
goto skip_egress_gateway;

info = lookup_ip4_egress_endpoint(ip4->saddr, ip4->daddr);
Expand Down
56 changes: 56 additions & 0 deletions bpf/lib/egress_policies.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2021 Authors of Cilium */

#ifndef __LIB_EGRESS_POLICIES_H_
#define __LIB_EGRESS_POLICIES_H_

#ifdef ENABLE_EGRESS_GATEWAY
/* is_cluster_destination returns true if the given destination is part of the
* cluster. It uses the ipcache and endpoint maps information.
*/
static __always_inline bool
is_cluster_destination(struct iphdr *ip4, __u32 dst_id, __u32 tunnel_endpoint)
{
/* If tunnel endpoint is found in ipcache, it means the remote endpoint
* is in cluster.
*/
if (tunnel_endpoint != 0)
return true;

/* If the destination is a Cilium-managed node (remote or local), it's
* part of the cluster.
*/
if (dst_id == REMOTE_NODE_ID || dst_id == HOST_ID)
return true;

/* Use the endpoint map to know if the destination is a local endpoint.
*/
if (lookup_ip4_endpoint(ip4))
return true;

/* Everything else is outside the cluster. */
return false;
}

/* EGRESS_STATIC_PREFIX gets sizeof non-IP, non-prefix part of egress_key */
# define EGRESS_STATIC_PREFIX \
(8 * (sizeof(struct egress_key) - sizeof(struct bpf_lpm_trie_key) \
- 4))
# define EGRESS_PREFIX_LEN(PREFIX) (EGRESS_STATIC_PREFIX + (PREFIX))
# define EGRESS_IPV4_PREFIX EGRESS_PREFIX_LEN(32)

static __always_inline __maybe_unused struct egress_info *
egress_lookup4(const void *map, __be32 sip, __be32 dip)
{
struct egress_key key = {
.lpm_key = { EGRESS_IPV4_PREFIX, {} },
.sip = sip,
.dip = dip,
};
return map_lookup_elem(map, &key);
}

# define lookup_ip4_egress_endpoint(sip, dip) \
egress_lookup4(&EGRESS_MAP, sip, dip)
#endif /* ENABLE_EGRESS_GATEWAY */
#endif /* __LIB_EGRESS_POLICIES_H_ */
24 changes: 0 additions & 24 deletions bpf/lib/eps.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,6 @@ lookup_ip4_endpoint_policy_map(__u32 ip)
- sizeof(union v6addr)))
#define IPCACHE_PREFIX_LEN(PREFIX) (IPCACHE_STATIC_PREFIX + (PREFIX))

/* EGRESS_STATIC_PREFIX gets sizeof non-IP, non-prefix part of ipcache_key */
#define EGRESS_STATIC_PREFIX \
(8 * (sizeof(struct egress_key) - sizeof(struct bpf_lpm_trie_key) \
- 4))
#define EGRESS_PREFIX_LEN(PREFIX) (EGRESS_STATIC_PREFIX + (PREFIX))
#define EGRESS_IPV4_PREFIX EGRESS_PREFIX_LEN(32)

#define V6_CACHE_KEY_LEN (sizeof(union v6addr)*8)

static __always_inline __maybe_unused struct remote_endpoint_info *
Expand Down Expand Up @@ -137,21 +130,4 @@ LPM_LOOKUP_FN(lookup_ip4_remote_endpoint, __be32, IPCACHE4_PREFIXES,
#define lookup_ip4_remote_endpoint(addr) \
ipcache_lookup4(&IPCACHE_MAP, addr, V4_CACHE_KEY_LEN)
#endif /* HAVE_LPM_TRIE_MAP_TYPE */

#ifdef ENABLE_EGRESS_GATEWAY
static __always_inline __maybe_unused struct egress_info *
egress_lookup4(const void *map, __be32 sip, __be32 dip)
{
struct egress_key key = {
.lpm_key = { EGRESS_IPV4_PREFIX, {} },
.sip = sip,
.dip = dip,
};
return map_lookup_elem(map, &key);
}

#define lookup_ip4_egress_endpoint(sip, dip) \
egress_lookup4(&EGRESS_MAP, sip, dip)
#endif /* ENABLE_EGRESS_GATEWAY */

#endif /* __LIB_EPS_H_ */
1 change: 1 addition & 0 deletions bpf/lib/nodeport.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "lb.h"
#include "common.h"
#include "overloadable.h"
#include "egress_policies.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: are there any policies that are not egress gw policies, that could be characterized as egress policies?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SRv6 egress policies are coming 😃

#include "eps.h"
#include "conntrack.h"
#include "csum.h"
Expand Down