go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/vppcalls/vpp2106/memif_vppcalls.go (about) 1 // Copyright (c) 2021 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 vpp2106 16 17 import ( 18 "context" 19 "fmt" 20 "io" 21 "strings" 22 23 "github.com/pkg/errors" 24 "go.fd.io/govpp/api" 25 26 "go.ligato.io/vpp-agent/v3/plugins/vpp" 27 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/interface_types" 28 vpp_memif "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/memif" 29 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls" 30 ifs "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 31 ) 32 33 func (h *InterfaceVppHandler) AddMemifInterface(ctx context.Context, ifName string, memIface *ifs.MemifLink, socketID uint32) (swIdx uint32, err error) { 34 if h.memif == nil { 35 return 0, errors.WithMessage(vpp.ErrPluginDisabled, "memif") 36 } 37 38 req := &vpp_memif.MemifCreate{ 39 ID: memIface.Id, 40 Mode: memifMode(memIface.Mode), 41 Secret: memIface.Secret, 42 SocketID: socketID, 43 BufferSize: uint16(memIface.BufferSize), 44 RingSize: memIface.RingSize, 45 RxQueues: uint8(memIface.RxQueues), 46 TxQueues: uint8(memIface.TxQueues), 47 } 48 if memIface.Master { 49 req.Role = 0 50 } else { 51 req.Role = 1 52 } 53 // TODO: temporary fix, waiting for https://gerrit.fd.io/r/#/c/7266/ 54 if req.RxQueues == 0 { 55 req.RxQueues = 1 56 } 57 if req.TxQueues == 0 { 58 req.TxQueues = 1 59 } 60 61 reply, err := h.memif.MemifCreate(ctx, req) 62 if err != nil { 63 return 0, err 64 } else if err = api.RetvalToVPPApiError(reply.Retval); err != nil { 65 return 0, err 66 } 67 swIdx = uint32(reply.SwIfIndex) 68 69 return swIdx, h.SetInterfaceTag(ifName, swIdx) 70 } 71 72 func (h *InterfaceVppHandler) DeleteMemifInterface(ctx context.Context, ifName string, idx uint32) error { 73 if h.memif == nil { 74 return errors.WithMessage(vpp.ErrPluginDisabled, "memif") 75 } 76 77 req := &vpp_memif.MemifDelete{ 78 SwIfIndex: interface_types.InterfaceIndex(idx), 79 } 80 if reply, err := h.memif.MemifDelete(ctx, req); err != nil { 81 return err 82 } else if err = api.RetvalToVPPApiError(reply.Retval); err != nil { 83 return err 84 } 85 86 return h.RemoveInterfaceTag(ifName, idx) 87 } 88 89 func (h *InterfaceVppHandler) RegisterMemifSocketFilename(ctx context.Context, filename string, id uint32) error { 90 if h.memif == nil { 91 return errors.WithMessage(vpp.ErrPluginDisabled, "memif") 92 } 93 94 req := &vpp_memif.MemifSocketFilenameAddDel{ 95 SocketFilename: filename, 96 SocketID: id, 97 IsAdd: true, // sockets can be added only 98 } 99 if reply, err := h.memif.MemifSocketFilenameAddDel(ctx, req); err != nil { 100 return err 101 } else if err = api.RetvalToVPPApiError(reply.Retval); err != nil { 102 return err 103 } 104 return nil 105 } 106 107 func memifMode(mode ifs.MemifLink_MemifMode) vpp_memif.MemifMode { 108 switch mode { 109 case ifs.MemifLink_IP: 110 return vpp_memif.MEMIF_MODE_API_IP 111 case ifs.MemifLink_PUNT_INJECT: 112 return vpp_memif.MEMIF_MODE_API_PUNT_INJECT 113 default: 114 return vpp_memif.MEMIF_MODE_API_ETHERNET 115 } 116 } 117 118 func (h *InterfaceVppHandler) DumpMemifSocketDetails(ctx context.Context) (map[string]uint32, error) { 119 if h.memif == nil { 120 return nil, errors.WithMessage(vpp.ErrPluginDisabled, "memif") 121 } 122 123 dump, err := h.memif.MemifSocketFilenameDump(ctx, &vpp_memif.MemifSocketFilenameDump{}) 124 if err != nil { 125 return nil, err 126 } 127 memifSocketMap := make(map[string]uint32) 128 for { 129 socketDetails, err := dump.Recv() 130 if err == io.EOF { 131 break 132 } 133 if err != nil { 134 return nil, err 135 } 136 137 filename := strings.SplitN(socketDetails.SocketFilename, "\x00", 2)[0] 138 memifSocketMap[filename] = socketDetails.SocketID 139 } 140 141 h.log.Debugf("Memif socket dump completed, found %d entries: %v", len(memifSocketMap), memifSocketMap) 142 143 return memifSocketMap, nil 144 } 145 146 // dumpMemifDetails dumps memif interface details from VPP and fills them into the provided interface map. 147 func (h *InterfaceVppHandler) dumpMemifDetails(ctx context.Context, interfaces map[uint32]*vppcalls.InterfaceDetails) error { 148 if h.memif == nil { 149 // no-op when disabled 150 return nil 151 } 152 153 memifSocketMap, err := h.DumpMemifSocketDetails(ctx) 154 if err != nil { 155 return fmt.Errorf("dumping memif socket details failed: %v", err) 156 } 157 158 dump, err := h.memif.MemifDump(ctx, &vpp_memif.MemifDump{}) 159 if err != nil { 160 return err 161 } 162 for { 163 memifDetails, err := dump.Recv() 164 if err == io.EOF { 165 break 166 } 167 if err != nil { 168 return err 169 } 170 171 _, ifIdxExists := interfaces[uint32(memifDetails.SwIfIndex)] 172 if !ifIdxExists { 173 continue 174 } 175 interfaces[uint32(memifDetails.SwIfIndex)].Interface.Link = &ifs.Interface_Memif{ 176 Memif: &ifs.MemifLink{ 177 Master: memifDetails.Role == 0, 178 Mode: memifModetoNB(memifDetails.Mode), 179 Id: memifDetails.ID, 180 // Secret: // TODO: Secret - not available in the binary API 181 SocketFilename: func(socketMap map[string]uint32) (filename string) { 182 for filename, id := range socketMap { 183 if memifDetails.SocketID == id { 184 return filename 185 } 186 } 187 // Socket for configured memif should exist 188 h.log.Warnf("Socket ID not found for memif %v", memifDetails.SwIfIndex) 189 return 190 }(memifSocketMap), 191 RingSize: memifDetails.RingSize, 192 BufferSize: uint32(memifDetails.BufferSize), 193 // TODO: RxQueues, TxQueues - not available in the binary API 194 // RxQueues: 195 // TxQueues: 196 }, 197 } 198 interfaces[uint32(memifDetails.SwIfIndex)].Interface.Type = ifs.Interface_MEMIF 199 } 200 201 return nil 202 }