-
Notifications
You must be signed in to change notification settings - Fork 3k
/
netlink.go
143 lines (124 loc) · 4.07 KB
/
netlink.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2017-2018 Authors of Cilium
//
// 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.
package loader
import (
"context"
"fmt"
"github.com/cilium/cilium/pkg/bpf"
"github.com/cilium/cilium/pkg/command/exec"
"github.com/vishvananda/netlink"
)
const (
libbpfFixupMsg = "struct bpf_elf_map fixup performed due to size mismatch!"
)
func replaceQdisc(ifName string) error {
link, err := netlink.LinkByName(ifName)
if err != nil {
return err
}
attrs := netlink.QdiscAttrs{
LinkIndex: link.Attrs().Index,
Handle: netlink.MakeHandle(0xffff, 0),
Parent: netlink.HANDLE_CLSACT,
}
qdisc := &netlink.GenericQdisc{
QdiscAttrs: attrs,
QdiscType: "clsact",
}
if err = netlink.QdiscReplace(qdisc); err != nil {
return fmt.Errorf("netlink: Replacing qdisc for %s failed: %s", ifName, err)
} else {
log.Debugf("netlink: Replacing qdisc for %s succeeded", ifName)
}
return nil
}
// replaceDatapath the qdisc and BPF program for a endpoint
func (l *Loader) replaceDatapath(ctx context.Context, ifName, objPath, progSec, progDirection string) error {
err := replaceQdisc(ifName)
if err != nil {
return fmt.Errorf("Failed to replace Qdisc for %s: %s", ifName, err)
}
// FIXME: Replace cilium-map-migrate with Golang map migration
cmd := exec.CommandContext(ctx, "cilium-map-migrate", "-s", objPath)
cmd.Env = bpf.Environment()
if _, err = cmd.CombinedOutput(log, true); err != nil {
return err
}
defer func() {
var retCode string
if err == nil {
retCode = "0"
} else {
retCode = "1"
}
args := []string{"-e", objPath, "-r", retCode}
cmd := exec.CommandContext(ctx, "cilium-map-migrate", args...)
cmd.Env = bpf.Environment()
_, _ = cmd.CombinedOutput(log, true) // ignore errors
}()
// FIXME: replace exec with native call
args := []string{"filter", "replace", "dev", ifName, progDirection,
"prio", "1", "handle", "1", "bpf", "da", "obj", objPath,
"sec", progSec,
}
cmd = exec.CommandContext(ctx, "tc", args...).WithFilters(libbpfFixupMsg)
_, err = cmd.CombinedOutput(log, true)
if err != nil {
return fmt.Errorf("Failed to load tc filter: %s", err)
}
return nil
}
// graftDatapath replaces obj in tail call map
func graftDatapath(ctx context.Context, mapPath, objPath, progSec string) error {
var err error
// FIXME: Replace cilium-map-migrate with Golang map migration
cmd := exec.CommandContext(ctx, "cilium-map-migrate", "-s", objPath)
cmd.Env = bpf.Environment()
if _, err = cmd.CombinedOutput(log, true); err != nil {
return err
}
defer func() {
var retCode string
if err == nil {
retCode = "0"
} else {
retCode = "1"
}
args := []string{"-e", objPath, "-r", retCode}
cmd := exec.CommandContext(ctx, "cilium-map-migrate", args...)
cmd.Env = bpf.Environment()
_, _ = cmd.CombinedOutput(log, true) // ignore errors
}()
// FIXME: replace exec with native call
// FIXME: only key 0 right now, could be made more flexible
args := []string{"exec", "bpf", "graft", mapPath, "key", "0",
"obj", objPath, "sec", progSec,
}
cmd = exec.CommandContext(ctx, "tc", args...).WithFilters(libbpfFixupMsg)
_, err = cmd.CombinedOutput(log, true)
if err != nil {
return fmt.Errorf("Failed to graft tc object: %s", err)
}
return nil
}
// DeleteDatapath filter from the given ifName
func (l *Loader) DeleteDatapath(ctx context.Context, ifName, direction string) error {
args := []string{"filter", "delete", "dev", ifName, direction}
cmd := exec.CommandContext(ctx, "tc", args...).WithFilters(libbpfFixupMsg)
_, err := cmd.CombinedOutput(log, true)
if err != nil {
return fmt.Errorf("Failed to remove tc filter: %s", err)
}
return nil
}