Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
88 lines (76 sloc) 3.08 KB
// Copyright (c) 2019 Tigera, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <linux/bpf.h>
#include "sockops.h"
struct bpf_map_def __attribute__((section("maps"))) calico_sk_endpoints = {
.type = BPF_MAP_TYPE_LPM_TRIE,
.key_size = sizeof(union ip4_bpf_lpm_trie_key),
.value_size = sizeof(__u32),
.max_entries = 65535,
.map_flags = BPF_F_NO_PREALLOC,
};
__attribute__((section("calico_sockops_func")))
enum bpf_ret_code calico_sockops(struct bpf_sock_ops *skops)
{
struct sock_key key = {};
union ip4_bpf_lpm_trie_key sip, dip;
__u32 sport, dport;
int err;
switch (skops->op) {
case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
/* local app established connection to remote server;
* fall through */
case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
/* remote client connected to local server */
break;
default:
/* other event we don't care about (I wish this was pub/sub!) */
return BPF_OK;
}
ip4val_to_lpm(&sip, 32, skops->local_ip4);
ip4val_to_lpm(&dip, 32, skops->remote_ip4);
// If neither source nor dest are present in the Felix-populated endoints
// map we do nothing because the packet is not related to Felix-managed
// traffic.
if ( NULL == bpf_map_lookup_elem(&calico_sk_endpoints, &dip)
&& NULL == bpf_map_lookup_elem(&calico_sk_endpoints, &sip) ) {
return BPF_OK;
}
sport = port_to_host(skops->local_port);
dport = safe_extract_port(skops->remote_port);
// We use the app's port and ip address as key. The socket attached
// to our in-kernel context will be stored as the value automatically.
if (sip.ip.addr == ENVOY_IP && sport == ENVOY_PORT) {
// If the source is envoy, the app is on the destination side.
// We set envoy_side to 1 so the sockmap-attached BPF program
// (sk_msg in redir.c) can identify packets going to envoy.
key.envoy_side = 1;
key.ip4 = dip.ip.addr;
key.port = dport;
} else {
// If the source IP is not envoy we assume it comes from the app (if it
// doesn't we won't find the socket in the sockmap and pass it to the
// rest of the stack). We use source port and ip.
//
// The destination IP/port is usually never envoy in our testing
// because we get executed before the destination address is rewritten
// by iptables so the packet from the app still has the destination
// address of some other service. We handle the general case.
key.ip4 = sip.ip.addr;
key.port = sport;
key.envoy_side = 0;
}
err = bpf_sock_hash_update(skops, &calico_sock_map, &key, BPF_ANY);
return BPF_OK;
}
char ____license[] __attribute__((section("license"))) = "Apache-2.0";
You can’t perform that action at this time.