go.ligato.io/vpp-agent/v3@v3.5.0/plugins/linux/ifplugin/descriptor/interface_tap.go (about) 1 // Copyright (c) 2018 Cisco and/or its affiliates. 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 "strings" 19 20 "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/linuxcalls" 21 22 "github.com/pkg/errors" 23 24 "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/ifaceidx" 25 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/linux/interfaces" 26 27 nslinuxcalls "go.ligato.io/vpp-agent/v3/plugins/linux/nsplugin/linuxcalls" 28 ) 29 30 // createTAPToVPP moves Linux-side of the VPP-TAP interface to the destination namespace 31 // and sets the requested host name, IP addresses, etc. 32 func (d *InterfaceDescriptor) createTAPToVPP( 33 nsCtx nslinuxcalls.NamespaceMgmtCtx, key string, linuxIf *interfaces.Interface, 34 ) ( 35 md *ifaceidx.LinuxIfMetadata, err error) { 36 37 // determine TAP interface name as set by VPP ifplugin 38 vppTapName := linuxIf.GetTap().GetVppTapIfName() 39 vppTapMeta, found := d.vppIfPlugin.GetInterfaceIndex().LookupByName(vppTapName) 40 if !found { 41 err = errors.Errorf("failed to find VPP-side for the TAP-To-VPP interface %s", linuxIf.Name) 42 d.log.Error(err) 43 return nil, err 44 } 45 vppTapHostName := vppTapMeta.TAPHostIfName 46 hostName := getHostIfName(linuxIf) 47 48 // context 49 agentPrefix := d.serviceLabel.GetAgentPrefix() 50 51 // add alias to associate TAP with the logical name and VPP-TAP reference 52 alias := agentPrefix + linuxcalls.GetTapAlias(linuxIf, vppTapHostName) 53 err = d.ifHandler.SetInterfaceAlias(vppTapHostName, alias) 54 if err != nil { 55 d.log.Error(err) 56 return nil, err 57 } 58 59 // move the TAP to the right namespace 60 err = d.setInterfaceNamespace(nsCtx, vppTapHostName, linuxIf.Namespace) 61 if err != nil { 62 d.log.Error(err) 63 return nil, err 64 } 65 66 // move to the namespace with the interface 67 revert, err := d.nsPlugin.SwitchToNamespace(nsCtx, linuxIf.Namespace) 68 if err != nil { 69 d.log.Error(err) 70 return nil, err 71 } 72 defer revert() 73 74 // rename from temporary host name to the request host name 75 if err := d.ifHandler.RenameInterface(vppTapHostName, hostName); err != nil { 76 d.log.Error(err) 77 return nil, err 78 } 79 80 // build metadata 81 link, err := d.ifHandler.GetLinkByName(hostName) 82 if err != nil { 83 d.log.Error(err) 84 return nil, err 85 } 86 87 return &ifaceidx.LinuxIfMetadata{ 88 VPPTapName: vppTapName, 89 Namespace: linuxIf.Namespace, 90 LinuxIfIndex: link.Attrs().Index, 91 }, nil 92 } 93 94 // deleteAutoTAP returns TAP interface back to the default namespace and renames 95 // the interface back to original name. 96 func (d *InterfaceDescriptor) deleteAutoTAP(nsCtx nslinuxcalls.NamespaceMgmtCtx, key string, linuxIf *interfaces.Interface, metadata *ifaceidx.LinuxIfMetadata) error { 97 hostName := getHostIfName(linuxIf) 98 agentPrefix := d.serviceLabel.GetAgentPrefix() 99 100 // get original TAP name 101 link, err := d.ifHandler.GetLinkByName(hostName) 102 if err != nil { 103 d.log.Error(err) 104 return err 105 } 106 alias := strings.TrimPrefix(link.Attrs().Alias, agentPrefix) 107 _, _, origVppTapHostName := linuxcalls.ParseTapAlias(alias) 108 if origVppTapHostName == "" { 109 err = errors.New("failed to obtain the original TAP host name") 110 d.log.Error(err) 111 return err 112 } 113 114 // rename back to the temporary name 115 err = d.ifHandler.RenameInterface(hostName, origVppTapHostName) 116 if err != nil { 117 d.log.Error(err) 118 return err 119 } 120 121 // move TAP back to the default namespace 122 err = d.setInterfaceNamespace(nsCtx, origVppTapHostName, nil) 123 if err != nil { 124 d.log.Error(err) 125 return err 126 } 127 128 // move to the default namespace 129 revert, err := d.nsPlugin.SwitchToNamespace(nsCtx, nil) 130 if err != nil { 131 d.log.Error(err) 132 return err 133 } 134 defer revert() 135 136 // remove interface alias at last(!) 137 // - actually vishvananda/netlink does not support alias removal, so we just change 138 // it to a string which is not prefixed with agent label 139 err = d.ifHandler.SetInterfaceAlias(origVppTapHostName, "unconfigured") 140 if err != nil { 141 d.log.Error(err) 142 return err 143 } 144 145 return nil 146 }