go.ligato.io/vpp-agent/v3@v3.5.0/plugins/linux/ifplugin/descriptor/interface_vrfdev.go (about) 1 // Copyright (c) 2020 Pantheon.tech 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 descriptor 16 17 import ( 18 "fmt" 19 "github.com/pkg/errors" 20 "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/linuxcalls" 21 22 "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/ifaceidx" 23 nslinuxcalls "go.ligato.io/vpp-agent/v3/plugins/linux/nsplugin/linuxcalls" 24 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/linux/interfaces" 25 ) 26 27 const ( 28 // Enabling this option allows a “global” listen socket to work across L3 master domains (e.g., VRFs). 29 sysctlL3MDevVar = "net.ipv4.tcp_l3mdev_accept" 30 ) 31 32 // createVRF creates a new VRF network device. 33 func (d *InterfaceDescriptor) createVRF( 34 nsCtx nslinuxcalls.NamespaceMgmtCtx, linuxIf *interfaces.Interface, 35 ) (md *ifaceidx.LinuxIfMetadata, err error) { 36 hostName := getHostIfName(linuxIf) 37 rt := linuxIf.GetVrfDev().GetRoutingTable() 38 agentPrefix := d.serviceLabel.GetAgentPrefix() 39 40 // move to the namespace with the interface 41 revert, err := d.nsPlugin.SwitchToNamespace(nsCtx, linuxIf.Namespace) 42 if err != nil { 43 d.log.Error("switch to namespace failed:", err) 44 return nil, err 45 } 46 defer revert() 47 48 // Enable child sockets to inherit the L3 master device index. 49 // Without this VRF cannot really be used. 50 err = d.enableL3MasterDev() 51 if err != nil { 52 return nil, err 53 } 54 55 // create a new VRF device 56 err = d.ifHandler.AddVRFDevice(hostName, rt) 57 if err != nil { 58 return nil, errors.WithMessagef(err, "failed to add VRF device %s (rt: %d)", hostName, rt) 59 } 60 61 // add alias 62 err = d.ifHandler.SetInterfaceAlias(hostName, agentPrefix+linuxcalls.GetVRFAlias(linuxIf)) 63 if err != nil { 64 return nil, errors.WithMessagef(err, "error setting VRF %s alias", hostName) 65 } 66 67 // build metadata 68 link, err := d.ifHandler.GetLinkByName(hostName) 69 if err != nil { 70 return nil, errors.WithMessagef(err, "error getting link %s", hostName) 71 } 72 73 return &ifaceidx.LinuxIfMetadata{ 74 Namespace: linuxIf.Namespace, 75 LinuxIfIndex: link.Attrs().Index, 76 HostIfName: hostName, 77 VrfDevRT: rt, 78 }, nil 79 } 80 81 // deleteVRF removes VRF network device. 82 func (d *InterfaceDescriptor) deleteVRF(linuxIf *interfaces.Interface) error { 83 hostName := getHostIfName(linuxIf) 84 err := d.ifHandler.DeleteInterface(hostName) 85 if err != nil { 86 d.log.Error(err) 87 return err 88 } 89 return nil 90 } 91 92 func (d *InterfaceDescriptor) enableL3MasterDev() error { 93 value, err := getSysctl(sysctlL3MDevVar) 94 if err != nil { 95 err = fmt.Errorf("could not read sysctl value for %s: %w", 96 sysctlL3MDevVar, err) 97 return err 98 } 99 if value == "0" { 100 _, err = setSysctl(sysctlL3MDevVar, "1") 101 if err != nil { 102 err = fmt.Errorf("failed to enable %s: %w", sysctlL3MDevVar, err) 103 return err 104 } 105 } 106 return nil 107 }