Skip to content

Commit

Permalink
init.sh,loader: load overlay programs in Go
Browse files Browse the repository at this point in the history
With this commit we remove code from init.sh that compiles and loads
programs from bpf_overlay.c. Without it init.sh isn't responsible for
loading bpf programs anymore, therefore none of the remaining commands
should depend on ciliums iproute2 fork.

Signed-off-by: Robin Gögge <r.goegge@isovalent.com>
  • Loading branch information
rgo3 authored and ti-mo committed Apr 19, 2023
1 parent 8193503 commit d38dda4
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 74 deletions.
69 changes: 1 addition & 68 deletions bpf/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -196,62 +196,6 @@ function rnd_mac_addr()
printf '%02x%s' $upper $lower
}

function bpf_compile()
{
IN=$1
OUT=$2
TYPE=$3
EXTRA_OPTS=$4

clang -O2 -target bpf -std=gnu89 -nostdinc -emit-llvm \
-g -Wall -Wextra -Werror -Wshadow \
-Wno-address-of-packed-member \
-Wno-unknown-warning-option \
-Wno-gnu-variable-sized-type-not-at-end \
-Wdeclaration-after-statement \
-Wimplicit-int-conversion -Wenum-conversion \
-I. -I$DIR -I$LIB -I$LIB/include \
-D__NR_CPUS__=$NR_CPUS \
-DENABLE_ARP_RESPONDER=1 \
$EXTRA_OPTS \
-c $LIB/$IN -o - | \
llc -march=bpf -mcpu=$MCPU -filetype=$TYPE -o $OUT
}

function bpf_unload()
{
DEV=$1
WHERE=$2

tc filter del dev $DEV $WHERE 2> /dev/null || true
}

function bpf_load()
{
DEV=$1
OPTS=$2
WHERE=$3
IN=$4
OUT=$5
SEC=$6
CALLS_MAP=$7

NODE_MAC=$(ip link show $DEV | grep ether | awk '{print $2}')
NODE_MAC="{.addr=$(mac2array $NODE_MAC)}"

OPTS="${OPTS} -DNODE_MAC=${NODE_MAC} -DCALLS_MAP=${CALLS_MAP}"
bpf_compile $IN $OUT obj "$OPTS"
tc qdisc replace dev $DEV clsact || true
[ -z "$(tc filter show dev $DEV $WHERE | grep -v "pref $FILTER_PRIO bpf chain 0 $\|pref $FILTER_PRIO bpf chain 0 handle 0x1")" ] || tc filter del dev $DEV $WHERE

cilium bpf migrate-maps -s "$OUT"

if ! tc filter replace dev "$DEV" "$WHERE" prio "$FILTER_PRIO" handle 1 bpf da obj "$OUT" sec "$SEC"; then
cilium bpf migrate-maps -e "$OUT" -r 1
return 1
fi
}

function create_encap_dev()
{
TUNNEL_OPTS="external"
Expand Down Expand Up @@ -407,17 +351,6 @@ if [ "${TUNNEL_MODE}" != "<nil>" ]; then
ENCAP_IDX=$(cat "${SYSCLASSNETDIR}/${ENCAP_DEV}/ifindex")
sed -i '/^#.*ENCAP_IFINDEX.*$/d' $RUNDIR/globals/node_config.h
echo "#define ENCAP_IFINDEX $ENCAP_IDX" >> $RUNDIR/globals/node_config.h

CALLS_MAP="cilium_calls_overlay_${ID_WORLD}"
COPTS="-DSECLABEL=${ID_WORLD} -DFROM_ENCAP_DEV=1"
if [ "$NODE_PORT" = "true" ]; then
COPTS="${COPTS} -DDISABLE_LOOPBACK_LB"
fi

bpf_load "$ENCAP_DEV" "$COPTS" ingress bpf_overlay.c bpf_overlay.o from-overlay "$CALLS_MAP"
bpf_load "$ENCAP_DEV" "$COPTS" egress bpf_overlay.c bpf_overlay.o to-overlay "$CALLS_MAP"

cilium bpf migrate-maps -e bpf_overlay.o -r 0
fi

if [ "$MODE" = "direct" ] || [ "$NODE_PORT" = "true" ] ; then
Expand Down Expand Up @@ -464,5 +397,5 @@ for iface in $(ip -o -a l | awk '{print $2}' | cut -d: -f1 | cut -d@ -f1 | grep
done

if [ "$HOST_DEV1" != "$HOST_DEV2" ]; then
bpf_unload $HOST_DEV2 "egress"
tc filter del dev $HOST_DEV2 "egress" 2> /dev/null || true
fi
51 changes: 45 additions & 6 deletions pkg/datapath/loader/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ import (
"github.com/cilium/cilium/pkg/datapath/prefilter"
datapath "github.com/cilium/cilium/pkg/datapath/types"
"github.com/cilium/cilium/pkg/defaults"
"github.com/cilium/cilium/pkg/identity"
ipamOption "github.com/cilium/cilium/pkg/ipam/option"
"github.com/cilium/cilium/pkg/logging/logfields"
"github.com/cilium/cilium/pkg/mac"
"github.com/cilium/cilium/pkg/node"
"github.com/cilium/cilium/pkg/option"
"github.com/cilium/cilium/pkg/socketlb"
Expand Down Expand Up @@ -210,6 +212,37 @@ func (l *Loader) reinitializeIPSec(ctx context.Context) error {
return nil
}

func (l *Loader) reinitializeOverlay(ctx context.Context, encapProto string) error {
// encapProto can be one of option.[TunnelDisabled, TunnelVXLAN, TunnelGeneve]
// if it is disabled, the overlay network programs don't have to be (re)initialized
if encapProto == option.TunnelDisabled {
return nil
}

iface := fmt.Sprintf("cilium_%s", encapProto)
link, err := netlink.LinkByName(iface)
if err != nil {
return fmt.Errorf("failed to retrieve link for interface %s: %w", iface, err)
}

// gather compile options for bpf_overlay.c
opts := []string{
fmt.Sprintf("-DSECLABEL=%d", identity.ReservedIdentityWorld),
fmt.Sprintf("-DNODE_MAC={.addr=%s}", mac.CArrayString(link.Attrs().HardwareAddr)),
fmt.Sprintf("-DCALLS_MAP=cilium_calls_overlay_%d", identity.ReservedIdentityWorld),
"-DFROM_ENCAP_DEV=1",
}
if option.Config.EnableNodePort {
opts = append(opts, "-DDISABLE_LOOPBACK_LB")
}

if err := l.replaceOverlayDatapath(ctx, opts, iface); err != nil {
return fmt.Errorf("failed to load overlay programs: %w", err)
}

return nil
}

func (l *Loader) reinitializeXDPLocked(ctx context.Context, extraCArgs []string) error {
maybeUnloadObsoleteXDPPrograms(option.Config.GetDevices(), option.Config.XDPMode)
if option.Config.XDPMode == option.XDPModeDisabled {
Expand Down Expand Up @@ -316,11 +349,11 @@ func (l *Loader) Reinitialize(ctx context.Context, o datapath.BaseProgramOwner,
}

var mode baseDeviceMode
args[initArgTunnelMode] = "<nil>"
encapProto := option.TunnelDisabled
switch {
case option.Config.TunnelingEnabled():
mode = tunnelMode
args[initArgTunnelMode] = option.Config.TunnelProtocol
encapProto = option.Config.TunnelProtocol
case option.Config.EnableHealthDatapath:
mode = option.DSRDispatchIPIP
sysSettings = append(sysSettings,
Expand All @@ -333,19 +366,21 @@ func (l *Loader) Reinitialize(ctx context.Context, o datapath.BaseProgramOwner,

if !option.Config.TunnelingEnabled() && option.Config.EnableIPv4EgressGateway {
// Tunnel is required for egress traffic under this config
args[initArgTunnelMode] = option.Config.TunnelProtocol
encapProto = option.Config.TunnelProtocol
}

if !option.Config.TunnelingEnabled() &&
option.Config.EnableNodePort &&
option.Config.NodePortMode == option.NodePortModeDSR &&
option.Config.LoadBalancerDSRDispatch == option.DSRDispatchGeneve {
args[initArgTunnelMode] = option.TunnelGeneve
encapProto = option.TunnelGeneve
}

// set init.sh args based on encapProto
args[initArgTunnelMode] = "<nil>"
args[initArgTunnelPort] = "<nil>"
switch args[initArgTunnelMode] {
case option.TunnelVXLAN, option.TunnelGeneve:
if encapProto != option.TunnelDisabled {
args[initArgTunnelMode] = encapProto
args[initArgTunnelPort] = fmt.Sprintf("%d", option.Config.TunnelPort)
}

Expand Down Expand Up @@ -447,6 +482,10 @@ func (l *Loader) Reinitialize(ctx context.Context, o datapath.BaseProgramOwner,
return err
}

if err := l.reinitializeOverlay(ctx, encapProto); err != nil {
return err
}

if err := o.Datapath().Node().NodeConfigurationChanged(*o.LocalConfig()); err != nil {
return err
}
Expand Down
44 changes: 44 additions & 0 deletions pkg/datapath/loader/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ const (
xdpPrefix = "bpf_xdp"
xdpProg = xdpPrefix + "." + string(outputSource)
xdpObj = xdpPrefix + ".o"

overlayPrefix = "bpf_overlay"
overlayProg = overlayPrefix + "." + string(outputSource)
overlayObj = overlayPrefix + ".o"
)

var (
Expand Down Expand Up @@ -447,3 +451,43 @@ func compileNetwork(ctx context.Context) error {
}
return nil
}

// compileOverlay compiles BPF programs in bpf_overlay.c.
func compileOverlay(ctx context.Context, opts []string) error {
dirs := &directoryInfo{
Library: option.Config.BpfDir,
Runtime: option.Config.StateDir,
Output: option.Config.StateDir,
State: option.Config.StateDir,
}
scopedLog := log.WithField(logfields.Debug, true)

versionCmd := exec.CommandContext(ctx, compiler, "--version")
compilerVersion, err := versionCmd.CombinedOutput(scopedLog, true)
if err != nil {
return err
}
versionCmd = exec.CommandContext(ctx, linker, "--version")
linkerVersion, err := versionCmd.CombinedOutput(scopedLog, true)
if err != nil {
return err
}
scopedLog.WithFields(logrus.Fields{
compiler: string(compilerVersion),
linker: string(linkerVersion),
}).Debug("Compiling overlay programs")

prog := &progInfo{
Source: overlayProg,
Output: overlayObj,
OutputType: outputObject,
Options: opts,
}
// Write out assembly and preprocessing files for debugging purposes
if err := compile(ctx, prog, dirs); err != nil {
scopedLog.WithField(logfields.Params, logfields.Repr(prog)).
WithError(err).Warn("Failed to compile")
return err
}
return nil
}
22 changes: 22 additions & 0 deletions pkg/datapath/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ const (

symbolFromHostNetdevXDP = "cil_xdp_entry"

symbolFromOverlay = "cil_from_overlay"
symbolToOverlay = "cil_to_overlay"

dirIngress = "ingress"
dirEgress = "egress"
)
Expand Down Expand Up @@ -354,6 +357,25 @@ func (l *Loader) replaceNetworkDatapath(ctx context.Context, interfaces []string
return nil
}

func (l *Loader) replaceOverlayDatapath(ctx context.Context, cArgs []string, iface string) error {
if err := compileOverlay(ctx, cArgs); err != nil {
log.WithError(err).Fatal("failed to compile overlay programs")
}

progs := []progDefinition{
{progName: symbolFromOverlay, direction: dirIngress},
{progName: symbolToOverlay, direction: dirEgress},
}

finalize, err := replaceDatapath(ctx, iface, overlayObj, progs, "")
if err != nil {
log.WithField(logfields.Interface, iface).WithError(err).Fatal("Load overlay network failed")
}
finalize()

return nil
}

func (l *Loader) compileAndLoad(ctx context.Context, ep datapath.Endpoint, dirs *directoryInfo, stats *metrics.SpanStat) error {
stats.BpfCompilation.Start()
err := compileDatapath(ctx, dirs, ep.IsHost(), ep.Logger(Subsystem))
Expand Down

0 comments on commit d38dda4

Please sign in to comment.