go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/l3plugin/vppcalls/vpp2101/arp_dump.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  	vpp_ip_neighbor "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/ip_neighbor"
    21  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/ip_types"
    22  	"go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls"
    23  	l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3"
    24  )
    25  
    26  // DumpArpEntries implements arp handler.
    27  func (h *ArpVppHandler) DumpArpEntries() ([]*vppcalls.ArpDetails, error) {
    28  	arpV4Entries, err := h.dumpArpEntries(false)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	arpV6Entries, err := h.dumpArpEntries(true)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	return append(arpV4Entries, arpV6Entries...), nil
    37  }
    38  
    39  func (h *ArpVppHandler) dumpArpEntries(isIPv6 bool) ([]*vppcalls.ArpDetails, error) {
    40  	var entries []*vppcalls.ArpDetails
    41  	req := &vpp_ip_neighbor.IPNeighborDump{
    42  		SwIfIndex: 0xffffffff, // Send multirequest to get all ARP entries for given IP version
    43  	}
    44  	if isIPv6 {
    45  		req.Af = ip_types.ADDRESS_IP6
    46  	}
    47  	reqCtx := h.callsChannel.SendMultiRequest(req)
    48  	for {
    49  		arpDetails := &vpp_ip_neighbor.IPNeighborDetails{}
    50  		stop, err := reqCtx.ReceiveReply(arpDetails)
    51  		if stop {
    52  			break
    53  		}
    54  		if err != nil {
    55  			h.log.Error(err)
    56  			return nil, err
    57  		}
    58  
    59  		// ARP interface
    60  		ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(uint32(arpDetails.Neighbor.SwIfIndex))
    61  		if !exists {
    62  			h.log.Warnf("ARP dump: interface name not found for index %d", arpDetails.Neighbor.SwIfIndex)
    63  		}
    64  		// IP & MAC address
    65  		var ip string
    66  		if arpDetails.Neighbor.IPAddress.Af == ip_types.ADDRESS_IP6 {
    67  			addr := arpDetails.Neighbor.IPAddress.Un.GetIP6()
    68  			ip = net.IP(addr[:]).To16().String()
    69  		} else {
    70  			addr := arpDetails.Neighbor.IPAddress.Un.GetIP4()
    71  			ip = net.IP(addr[:]).To4().String()
    72  		}
    73  
    74  		// ARP entry
    75  		arp := &l3.ARPEntry{
    76  			Interface:   ifName,
    77  			IpAddress:   ip,
    78  			PhysAddress: net.HardwareAddr(arpDetails.Neighbor.MacAddress[:]).String(),
    79  			Static:      arpDetails.Neighbor.Flags&vpp_ip_neighbor.IP_API_NEIGHBOR_FLAG_STATIC != 0,
    80  		}
    81  		// ARP meta
    82  		meta := &vppcalls.ArpMeta{
    83  			SwIfIndex: uint32(arpDetails.Neighbor.SwIfIndex),
    84  		}
    85  
    86  		entries = append(entries, &vppcalls.ArpDetails{
    87  			Arp:  arp,
    88  			Meta: meta,
    89  		})
    90  	}
    91  
    92  	return entries, nil
    93  }