go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/srplugin/vppcalls/vpp2202/srv6_dump.go (about)

     1  // Copyright (c) 2022 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 vpp2202
    16  
    17  import (
    18  	"net"
    19  
    20  	"github.com/go-errors/errors"
    21  
    22  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/ip_types"
    23  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/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  }