github.com/looshlee/cilium@v1.6.12/plugins/cilium-cni/chaining/flannel/flannel.go (about) 1 // Copyright 2019 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 flannel 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 22 "github.com/cilium/cilium/api/v1/models" 23 "github.com/cilium/cilium/pkg/logging/logfields" 24 chainingapi "github.com/cilium/cilium/plugins/cilium-cni/chaining/api" 25 26 cniTypesVer "github.com/containernetworking/cni/pkg/types/current" 27 cniVersion "github.com/containernetworking/cni/pkg/version" 28 "github.com/sirupsen/logrus" 29 "github.com/vishvananda/netlink" 30 ) 31 32 type flannelChainer struct{} 33 34 func (f *flannelChainer) ImplementsAdd() bool { 35 return true 36 } 37 38 func (f *flannelChainer) Add(ctx context.Context, pluginCtx chainingapi.PluginContext) (res *cniTypesVer.Result, err error) { 39 err = cniVersion.ParsePrevResult(&pluginCtx.NetConf.NetConf) 40 if err != nil { 41 return nil, fmt.Errorf("unable to understand network config: %s", err) 42 } 43 r, err := cniTypesVer.GetResult(pluginCtx.NetConf.PrevResult) 44 if err != nil { 45 return nil, fmt.Errorf("unable to get previous network result: %s", err) 46 } 47 // We only care about the veth interface that is on the host side 48 // and cni0. Interfaces should be similar as: 49 // "interfaces":[ 50 // { 51 // "name":"cni0", 52 // "mac":"0a:58:0a:f4:00:01" 53 // }, 54 // { 55 // "name":"veth15707e9b", 56 // "mac":"4e:6d:93:35:6b:45" 57 // }, 58 // { 59 // "name":"eth0", 60 // "mac":"0a:58:0a:f4:00:06", 61 // "sandbox":"/proc/15259/ns/net" 62 // } 63 // ] 64 65 defer func() { 66 if err != nil { 67 pluginCtx.Logger.WithError(err). 68 WithFields(logrus.Fields{"cni-pre-result": pluginCtx.NetConf.PrevResult.String()}). 69 Errorf("Unable to create endpoint") 70 } 71 }() 72 var ( 73 hostMac, vethHostName, vethLXCMac, vethIP string 74 vethHostIdx, vethSliceIdx int 75 ) 76 for i, iDev := range r.Interfaces { 77 // We only care about the veth interface mac address on the container side. 78 if iDev.Sandbox != "" { 79 vethLXCMac = iDev.Mac 80 vethSliceIdx = i 81 continue 82 } 83 84 l, err := netlink.LinkByName(iDev.Name) 85 if err != nil { 86 continue 87 } 88 switch l.Type() { 89 case "veth": 90 vethHostName = iDev.Name 91 vethHostIdx = l.Attrs().Index 92 case "bridge": 93 // likely to be cni0 94 hostMac = iDev.Mac 95 } 96 } 97 for _, ipCfg := range r.IPs { 98 if ipCfg.Interface != nil && *ipCfg.Interface == vethSliceIdx { 99 vethIP = ipCfg.Address.IP.String() 100 break 101 } 102 } 103 switch { 104 case hostMac == "": 105 return nil, errors.New("unable to determine MAC address of bridge interface (cni0)") 106 case vethHostName == "": 107 return nil, errors.New("unable to determine name of veth pair on the host side") 108 case vethLXCMac == "": 109 return nil, errors.New("unable to determine MAC address of veth pair on the container side") 110 case vethIP == "": 111 return nil, errors.New("unable to determine IP address of the container") 112 case vethHostIdx == 0: 113 return nil, errors.New("unable to determine index interface of veth pair on the host side") 114 } 115 116 ep := &models.EndpointChangeRequest{ 117 Addressing: &models.AddressPair{ 118 IPV4: vethIP, 119 }, 120 ContainerID: pluginCtx.Args.ContainerID, 121 State: models.EndpointStateWaitingForIdentity, 122 HostMac: hostMac, 123 InterfaceIndex: int64(vethHostIdx), 124 Mac: vethLXCMac, 125 InterfaceName: vethHostName, 126 K8sPodName: string(pluginCtx.CniArgs.K8S_POD_NAME), 127 K8sNamespace: string(pluginCtx.CniArgs.K8S_POD_NAMESPACE), 128 SyncBuildEndpoint: true, 129 } 130 131 err = pluginCtx.Client.EndpointCreate(ep) 132 if err != nil { 133 pluginCtx.Logger.WithError(err).WithFields(logrus.Fields{ 134 logfields.ContainerID: ep.ContainerID}).Warn("Unable to create endpoint") 135 err = fmt.Errorf("unable to create endpoint: %s", err) 136 return 137 } 138 139 pluginCtx.Logger.WithFields(logrus.Fields{ 140 logfields.ContainerID: ep.ContainerID}).Debug("Endpoint successfully created") 141 return r, nil 142 } 143 144 func (f *flannelChainer) ImplementsDelete() bool { 145 return false 146 } 147 148 func (f *flannelChainer) Delete(ctx context.Context, pluginCtx chainingapi.PluginContext) (err error) { 149 return nil 150 } 151 152 func init() { 153 chainingapi.Register("cbr0", &flannelChainer{}) 154 }