github.com/elfadel/cilium@v1.6.12/pkg/datapath/loader/netlink.go (about) 1 // Copyright 2017-2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package loader 16 17 import ( 18 "context" 19 "fmt" 20 21 "github.com/cilium/cilium/pkg/bpf" 22 "github.com/cilium/cilium/pkg/command/exec" 23 24 "github.com/vishvananda/netlink" 25 ) 26 27 const ( 28 libbpfFixupMsg = "struct bpf_elf_map fixup performed due to size mismatch!" 29 ) 30 31 func replaceQdisc(ifName string) error { 32 link, err := netlink.LinkByName(ifName) 33 if err != nil { 34 return err 35 } 36 attrs := netlink.QdiscAttrs{ 37 LinkIndex: link.Attrs().Index, 38 Handle: netlink.MakeHandle(0xffff, 0), 39 Parent: netlink.HANDLE_CLSACT, 40 } 41 42 qdisc := &netlink.GenericQdisc{ 43 QdiscAttrs: attrs, 44 QdiscType: "clsact", 45 } 46 47 if err = netlink.QdiscReplace(qdisc); err != nil { 48 return fmt.Errorf("netlink: Replacing qdisc for %s failed: %s", ifName, err) 49 } else { 50 log.Debugf("netlink: Replacing qdisc for %s succeeded", ifName) 51 } 52 53 return nil 54 } 55 56 // replaceDatapath the qdisc and BPF program for a endpoint 57 func replaceDatapath(ctx context.Context, ifName, objPath, progSec, progDirection string) error { 58 err := replaceQdisc(ifName) 59 if err != nil { 60 return fmt.Errorf("Failed to replace Qdisc for %s: %s", ifName, err) 61 } 62 63 // FIXME: Replace cilium-map-migrate with Golang map migration 64 cmd := exec.CommandContext(ctx, "cilium-map-migrate", "-s", objPath) 65 cmd.Env = bpf.Environment() 66 if _, err = cmd.CombinedOutput(log, true); err != nil { 67 return err 68 } 69 defer func() { 70 var retCode string 71 if err == nil { 72 retCode = "0" 73 } else { 74 retCode = "1" 75 } 76 args := []string{"-e", objPath, "-r", retCode} 77 cmd := exec.CommandContext(ctx, "cilium-map-migrate", args...) 78 cmd.Env = bpf.Environment() 79 _, _ = cmd.CombinedOutput(log, true) // ignore errors 80 }() 81 82 // FIXME: replace exec with native call 83 args := []string{"filter", "replace", "dev", ifName, progDirection, 84 "prio", "1", "handle", "1", "bpf", "da", "obj", objPath, 85 "sec", progSec, 86 } 87 cmd = exec.CommandContext(ctx, "tc", args...).WithFilters(libbpfFixupMsg) 88 _, err = cmd.CombinedOutput(log, true) 89 if err != nil { 90 return fmt.Errorf("Failed to load tc filter: %s", err) 91 } 92 93 return nil 94 } 95 96 // graftDatapath replaces obj in tail call map 97 func graftDatapath(ctx context.Context, mapPath, objPath, progSec string) error { 98 var err error 99 100 // FIXME: Replace cilium-map-migrate with Golang map migration 101 cmd := exec.CommandContext(ctx, "cilium-map-migrate", "-s", objPath) 102 cmd.Env = bpf.Environment() 103 if _, err = cmd.CombinedOutput(log, true); err != nil { 104 return err 105 } 106 defer func() { 107 var retCode string 108 if err == nil { 109 retCode = "0" 110 } else { 111 retCode = "1" 112 } 113 args := []string{"-e", objPath, "-r", retCode} 114 cmd := exec.CommandContext(ctx, "cilium-map-migrate", args...) 115 cmd.Env = bpf.Environment() 116 _, _ = cmd.CombinedOutput(log, true) // ignore errors 117 }() 118 119 // FIXME: replace exec with native call 120 // FIXME: only key 0 right now, could be made more flexible 121 args := []string{"exec", "bpf", "graft", mapPath, "key", "0", 122 "obj", objPath, "sec", progSec, 123 } 124 cmd = exec.CommandContext(ctx, "tc", args...).WithFilters(libbpfFixupMsg) 125 _, err = cmd.CombinedOutput(log, true) 126 if err != nil { 127 return fmt.Errorf("Failed to graft tc object: %s", err) 128 } 129 130 return nil 131 } 132 133 // DeleteDatapath filter from the given ifName 134 func DeleteDatapath(ctx context.Context, ifName, direction string) error { 135 args := []string{"filter", "delete", "dev", ifName, direction, "pref", "1", "handle", "1", "bpf"} 136 cmd := exec.CommandContext(ctx, "tc", args...).WithFilters(libbpfFixupMsg) 137 _, err := cmd.CombinedOutput(log, true) 138 if err != nil { 139 return fmt.Errorf("Failed to remove tc filter: %s", err) 140 } 141 142 return nil 143 }