go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/srplugin/vppcalls/vpp2106/srv6_dump.go (about) 1 // Copyright (c) 2021 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 vpp2106 16 17 import ( 18 "net" 19 20 "github.com/go-errors/errors" 21 22 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/ip_types" 23 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/sr" 24 srv6 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/srv6" 25 ) 26 27 // DumpLocalSids retrieves all localsids 28 func (h *SRv6VppHandler) DumpLocalSids() (localsids []*srv6.LocalSID, err error) { 29 h.log.Debug("Dumping LocalSIDs") 30 31 reqCtx := h.callsChannel.SendMultiRequest(&sr.SrLocalsidsDump{}) 32 for { 33 // retrieve dump for another localsid 34 dumpReply := &sr.SrLocalsidsDetails{} 35 stop, err := reqCtx.ReceiveReply(dumpReply) 36 if stop { 37 break 38 } 39 if err != nil { 40 return nil, errors.Errorf("error while retrieving localsid details:%v", err) 41 } 42 43 // convert dumped localsid details into modeled Localsid struct 44 sid, error := h.convertDumpedSid(&dumpReply.Addr) 45 if error != nil { 46 return localsids, errors.Errorf("can't properly handle sid address "+ 47 "of dumped localsid %v due to: %v", dumpReply, err) 48 } 49 localsid := &srv6.LocalSID{ 50 InstallationVrfId: dumpReply.FibTable, 51 Sid: sid.String(), 52 } 53 if err := h.fillEndFunction(localsid, dumpReply); err != nil { 54 return localsids, errors.Errorf("can't properly handle end function "+ 55 "of dumped localsid %v due to: %v", dumpReply, err) 56 } 57 58 // collect all dumped localsids 59 localsids = append(localsids, localsid) 60 } 61 62 return localsids, nil 63 } 64 65 // convertDumpedSid extract from dumped structure SID value and converts it to IPv6 (net.IP) 66 func (h *SRv6VppHandler) convertDumpedSid(srv6Sid *ip_types.IP6Address) (net.IP, error) { 67 if srv6Sid == nil { 68 return nil, errors.New("can't convert sid from nil dumped address (or nil srv6sid)") 69 } 70 sid := net.IP(srv6Sid[:]).To16() 71 if sid == nil { 72 return nil, errors.Errorf("can't convert dumped SID bytes(%v) to net.IP", srv6Sid) 73 } 74 return sid, nil 75 } 76 77 // fillEndFunction create end function part of NB-modeled localsid from SB-dumped structure 78 func (h *SRv6VppHandler) fillEndFunction(localSID *srv6.LocalSID, dumpReply *sr.SrLocalsidsDetails) error { 79 switch uint8(dumpReply.Behavior) { 80 case BehaviorEnd: 81 localSID.EndFunction = &srv6.LocalSID_BaseEndFunction{ 82 BaseEndFunction: &srv6.LocalSID_End{ 83 Psp: dumpReply.EndPsp, 84 }, 85 } 86 case BehaviorX: 87 ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(dumpReply.XconnectIfaceOrVrfTable) 88 if !exists { 89 return errors.Errorf("there is no interface with sw index %v", dumpReply.XconnectIfaceOrVrfTable) 90 } 91 localSID.EndFunction = &srv6.LocalSID_EndFunctionX{ 92 EndFunctionX: &srv6.LocalSID_EndX{ 93 Psp: dumpReply.EndPsp, 94 OutgoingInterface: ifName, 95 NextHop: h.nextHop(dumpReply), 96 }, 97 } 98 case BehaviorT: 99 localSID.EndFunction = &srv6.LocalSID_EndFunctionT{ 100 EndFunctionT: &srv6.LocalSID_EndT{ 101 Psp: dumpReply.EndPsp, 102 VrfId: dumpReply.XconnectIfaceOrVrfTable, 103 }, 104 } 105 case BehaviorDX2: 106 ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(dumpReply.XconnectIfaceOrVrfTable) 107 if !exists { 108 return errors.Errorf("there is no interface with sw index %v", dumpReply.XconnectIfaceOrVrfTable) 109 } 110 localSID.EndFunction = &srv6.LocalSID_EndFunctionDx2{ 111 EndFunctionDx2: &srv6.LocalSID_EndDX2{ 112 VlanTag: dumpReply.VlanIndex, 113 OutgoingInterface: ifName, 114 }, 115 } 116 case BehaviorDX4: 117 ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(dumpReply.XconnectIfaceOrVrfTable) 118 if !exists { 119 return errors.Errorf("there is no interface with sw index %v", dumpReply.XconnectIfaceOrVrfTable) 120 } 121 localSID.EndFunction = &srv6.LocalSID_EndFunctionDx4{ 122 EndFunctionDx4: &srv6.LocalSID_EndDX4{ 123 OutgoingInterface: ifName, 124 NextHop: h.nextHop(dumpReply), 125 }, 126 } 127 case BehaviorDX6: 128 ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(dumpReply.XconnectIfaceOrVrfTable) 129 if !exists { 130 return errors.Errorf("there is no interface with sw index %v", dumpReply.XconnectIfaceOrVrfTable) 131 } 132 localSID.EndFunction = &srv6.LocalSID_EndFunctionDx6{ 133 EndFunctionDx6: &srv6.LocalSID_EndDX6{ 134 OutgoingInterface: ifName, 135 NextHop: h.nextHop(dumpReply), 136 }, 137 } 138 case BehaviorDT4: 139 localSID.EndFunction = &srv6.LocalSID_EndFunctionDt4{ 140 EndFunctionDt4: &srv6.LocalSID_EndDT4{ 141 VrfId: dumpReply.XconnectIfaceOrVrfTable, 142 }, 143 } 144 case BehaviorDT6: 145 localSID.EndFunction = &srv6.LocalSID_EndFunctionDt6{ 146 EndFunctionDt6: &srv6.LocalSID_EndDT6{ 147 VrfId: dumpReply.XconnectIfaceOrVrfTable, 148 }, 149 } 150 default: 151 return errors.Errorf("localsid with unknown or unsupported behavior (%v)", dumpReply.Behavior) 152 } 153 154 return nil 155 } 156 157 // nextHop transforms SB dump data about next hop to NB modeled structure 158 func (h *SRv6VppHandler) nextHop(dumpReply *sr.SrLocalsidsDetails) string { 159 ip := addressToIP(dumpReply.XconnectNhAddr) 160 if ip.IsUnspecified() { 161 // default is no next hop address (i.e. L2 xconnect) 162 return "" 163 } 164 return ip.String() 165 }