go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/abfplugin/vppcalls/vpp2101/dump_abf_vppcalls.go (about)

     1  //  Copyright (c) 2019 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 vpp2101
    16  
    17  import (
    18  	"net"
    19  
    20  	"go.ligato.io/vpp-agent/v3/plugins/vpp/abfplugin/vppcalls"
    21  	vpp_abf "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/abf"
    22  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/fib_types"
    23  	abf "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/abf"
    24  )
    25  
    26  // placeholder for unknown names
    27  const unknownName = "<unknown>"
    28  
    29  // DumpABFPolicy retrieves VPP ABF configuration.
    30  func (h *ABFVppHandler) DumpABFPolicy() ([]*vppcalls.ABFDetails, error) {
    31  	// retrieve ABF interfaces
    32  	attachedIfs, err := h.dumpABFInterfaces()
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	// retrieve ABF policy
    38  	abfPolicy, err := h.dumpABFPolicy()
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	// merge attached interfaces data to policy
    44  	for _, policy := range abfPolicy {
    45  		ifData, ok := attachedIfs[policy.Meta.PolicyID]
    46  		if ok {
    47  			policy.ABF.AttachedInterfaces = ifData
    48  		}
    49  	}
    50  
    51  	return abfPolicy, nil
    52  }
    53  
    54  func (h *ABFVppHandler) dumpABFInterfaces() (map[uint32][]*abf.ABF_AttachedInterface, error) {
    55  	// ABF index <-> attached interfaces
    56  	abfIfs := make(map[uint32][]*abf.ABF_AttachedInterface)
    57  
    58  	req := &vpp_abf.AbfItfAttachDump{}
    59  	reqCtx := h.callsChannel.SendMultiRequest(req)
    60  
    61  	for {
    62  		reply := &vpp_abf.AbfItfAttachDetails{}
    63  		last, err := reqCtx.ReceiveReply(reply)
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  		if last {
    68  			break
    69  		}
    70  
    71  		// interface name
    72  		ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(uint32(reply.Attach.SwIfIndex))
    73  		if !exists {
    74  			ifName = unknownName
    75  		}
    76  
    77  		// attached interface entry
    78  		attached := &abf.ABF_AttachedInterface{
    79  			InputInterface: ifName,
    80  			Priority:       reply.Attach.Priority,
    81  			IsIpv6:         reply.Attach.IsIPv6,
    82  		}
    83  
    84  		_, ok := abfIfs[reply.Attach.PolicyID]
    85  		if !ok {
    86  			abfIfs[reply.Attach.PolicyID] = []*abf.ABF_AttachedInterface{}
    87  		}
    88  		abfIfs[reply.Attach.PolicyID] = append(abfIfs[reply.Attach.PolicyID], attached)
    89  	}
    90  
    91  	return abfIfs, nil
    92  }
    93  
    94  func (h *ABFVppHandler) dumpABFPolicy() ([]*vppcalls.ABFDetails, error) {
    95  	var abfs []*vppcalls.ABFDetails
    96  	req := &vpp_abf.AbfPolicyDump{}
    97  	reqCtx := h.callsChannel.SendMultiRequest(req)
    98  
    99  	for {
   100  		reply := &vpp_abf.AbfPolicyDetails{}
   101  		last, err := reqCtx.ReceiveReply(reply)
   102  		if err != nil {
   103  			return nil, err
   104  		}
   105  		if last {
   106  			break
   107  		}
   108  
   109  		// ACL name
   110  		aclName, _, exists := h.aclIndexes.LookupByIndex(reply.Policy.ACLIndex)
   111  		if !exists {
   112  			aclName = unknownName
   113  		}
   114  
   115  		// paths
   116  		var fwdPaths []*abf.ABF_ForwardingPath
   117  		for _, path := range reply.Policy.Paths {
   118  			// interface name
   119  			ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(path.SwIfIndex)
   120  			if !exists {
   121  				ifName = unknownName
   122  			}
   123  
   124  			// base fields
   125  			fwdPath := &abf.ABF_ForwardingPath{
   126  				NextHopIp:     parseNextHopToString(path.Nh, path.Proto),
   127  				InterfaceName: ifName,
   128  				Weight:        uint32(path.Weight),
   129  				Preference:    uint32(path.Preference),
   130  				Dvr:           path.Type == fib_types.FIB_API_PATH_TYPE_DVR,
   131  			}
   132  			fwdPaths = append(fwdPaths, fwdPath)
   133  		}
   134  
   135  		abfData := &vppcalls.ABFDetails{
   136  			ABF: &abf.ABF{
   137  				Index:           reply.Policy.PolicyID,
   138  				AclName:         aclName,
   139  				ForwardingPaths: fwdPaths,
   140  			},
   141  			Meta: &vppcalls.ABFMeta{
   142  				PolicyID: reply.Policy.PolicyID,
   143  			},
   144  		}
   145  
   146  		abfs = append(abfs, abfData)
   147  	}
   148  
   149  	return abfs, nil
   150  }
   151  
   152  // returns next hop IP address
   153  func parseNextHopToString(nh fib_types.FibPathNh, proto fib_types.FibPathNhProto) string {
   154  	if proto == fib_types.FIB_API_PATH_NH_PROTO_IP4 {
   155  		addr := nh.Address.GetIP4()
   156  		return net.IP(addr[:]).To4().String()
   157  	}
   158  	if proto == fib_types.FIB_API_PATH_NH_PROTO_IP6 {
   159  		addr := nh.Address.GetIP6()
   160  		return net.IP(addr[:]).To16().String()
   161  	}
   162  	return ""
   163  }