text: package vpp1904
  
  import (
  	"fmt"
  
  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp1904/span"
  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls"
  )
  
  // SetSpan enables or disables SPAN on interface
  func (h *InterfaceVppHandler) setSpan(ifIdxFrom, ifIdxTo uint32, state uint8, isL2 bool) error {
  	req := &span.SwInterfaceSpanEnableDisable{
  		SwIfIndexFrom: ifIdxFrom,
  		SwIfIndexTo:   ifIdxTo,
  		State:         state,
  		IsL2:          boolToUint(isL2),
  	}
  	reply := &span.SwInterfaceSpanEnableDisableReply{}
  
  	if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
  		return err
  	}
  
  	return nil
  }
  
  // AddSpan enables SPAN on interface
  func (h *InterfaceVppHandler) AddSpan(ifIdxFrom, ifIdxTo uint32, direction uint8, isL2 bool) error {
  	return h.setSpan(ifIdxFrom, ifIdxTo, direction, isL2)
  }
  
  // DelSpan disables SPAN on interface
  func (h *InterfaceVppHandler) DelSpan(ifIdxFrom, ifIdxTo uint32, isL2 bool) error {
  	return h.setSpan(ifIdxFrom, ifIdxTo, 0, isL2)
  }
  
  // DumpSpan dumps all SPAN table
  func (h *InterfaceVppHandler) DumpSpan() ([]*vppcalls.InterfaceSpanDetails, error) {
  	var spans []*vppcalls.InterfaceSpanDetails
  
  	isL2Spans, err := h.dumpSpan(&span.SwInterfaceSpanDump{IsL2: 1})
  	if err != nil {
  		return nil, err
  	}
  	spans = append(spans, isL2Spans...)
  
  	isNotL2Spans, err := h.dumpSpan(&span.SwInterfaceSpanDump{IsL2: 0})
  	if err != nil {
  		return nil, err
  	}
  	spans = append(spans, isNotL2Spans...)
  
  	return spans, nil
  }
  
  // dumpIsL2Span returns only SPANs with or without L2 set
  func (h *InterfaceVppHandler) dumpSpan(msg *span.SwInterfaceSpanDump) ([]*vppcalls.InterfaceSpanDetails, error) {
  	var spans []*vppcalls.InterfaceSpanDetails
  
  	reqCtx := h.callsChannel.SendMultiRequest(msg)
  	for {
  		spanDetails := &span.SwInterfaceSpanDetails{}
  		stop, err := reqCtx.ReceiveReply(spanDetails)
  		if stop {
  			break
  		}
  		if err != nil {
  			return nil, fmt.Errorf("failed to dump span: %v", err)
  		}
  
  		span := &vppcalls.InterfaceSpanDetails{
  			SwIfIndexFrom: spanDetails.SwIfIndexFrom,
  			SwIfIndexTo:   spanDetails.SwIfIndexTo,
  			Direction:     spanDetails.State,
  			IsL2:          spanDetails.IsL2 > 0,
  		}
  		spans = append(spans, span)
  	}
  	return spans, nil
  }
  