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

     1  //  Copyright (c) 2020 Doc.ai 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  	"encoding/base64"
    19  	"fmt"
    20  	"github.com/pkg/errors"
    21  	"go.ligato.io/vpp-agent/v3/plugins/vpp"
    22  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/interface_types"
    23  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/wireguard"
    24  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls"
    25  	interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    26  )
    27  
    28  // AddWireguardTunnel adds a new wireguard tunnel interface.
    29  func (h *InterfaceVppHandler) AddWireguardTunnel(ifName string, wireguardLink *interfaces.WireguardLink) (uint32, error) {
    30  	invalidIdx := ^uint32(0)
    31  	if h.wireguard == nil {
    32  		return invalidIdx, errors.WithMessage(vpp.ErrPluginDisabled, "wireguard")
    33  	}
    34  
    35  	wgItf := wireguard.WireguardInterface{
    36  		UserInstance: ^uint32(0),
    37  		Port:         uint16(wireguardLink.Port),
    38  	}
    39  
    40  	genKey := false
    41  	if len(wireguardLink.PrivateKey) > 0 {
    42  		publicKeyBin, err := base64.StdEncoding.DecodeString(wireguardLink.PrivateKey)
    43  		if err != nil {
    44  			return invalidIdx, err
    45  		}
    46  		wgItf.PrivateKey = publicKeyBin
    47  	} else {
    48  		genKey = true
    49  	}
    50  
    51  	srcAddr, err := IPToAddress(wireguardLink.SrcAddr)
    52  	if err != nil {
    53  		return invalidIdx, err
    54  	}
    55  	wgItf.SrcIP = srcAddr
    56  
    57  	req := &wireguard.WireguardInterfaceCreate{
    58  		Interface:   wgItf,
    59  		GenerateKey: genKey,
    60  	}
    61  
    62  	// prepare reply
    63  	reply := &wireguard.WireguardInterfaceCreateReply{}
    64  	// send request and obtain reply
    65  	if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
    66  		return ^uint32(0), err
    67  	}
    68  	retSwIfIndex := uint32(reply.SwIfIndex)
    69  	return retSwIfIndex, h.SetInterfaceTag(ifName, retSwIfIndex)
    70  }
    71  
    72  // DeleteWireguardTunnel removes wireguard tunnel interface.
    73  func (h *InterfaceVppHandler) DeleteWireguardTunnel(ifName string, ifIdx uint32) error {
    74  	if h.wireguard == nil {
    75  		return errors.WithMessage(vpp.ErrPluginDisabled, "wireguard")
    76  	}
    77  
    78  	req := &wireguard.WireguardInterfaceDelete{
    79  		SwIfIndex: interface_types.InterfaceIndex(ifIdx),
    80  	}
    81  	// prepare reply
    82  	reply := &wireguard.WireguardInterfaceDeleteReply{}
    83  	// send request and obtain reply
    84  
    85  	if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
    86  		return err
    87  	}
    88  	return h.RemoveInterfaceTag(ifName, ifIdx);
    89  }
    90  
    91  // dumpWireguardDetails dumps wireguard interface details from VPP.
    92  func (h *InterfaceVppHandler) dumpWireguardDetails(ifc map[uint32]*vppcalls.InterfaceDetails) error {
    93  	if h.wireguard == nil {
    94  		return nil
    95  	}
    96  
    97  	reqCtx := h.callsChannel.SendMultiRequest(&wireguard.WireguardInterfaceDump{})
    98  
    99  	for {
   100  		wgDetails := &wireguard.WireguardInterfaceDetails{}
   101  		stop, err := reqCtx.ReceiveReply(wgDetails)
   102  		if stop {
   103  			break // Break from the loop.
   104  		}
   105  		if err != nil {
   106  			return fmt.Errorf("failed to dump wireguard interface details: %v", err)
   107  		}
   108  		_, ifIdxExists := ifc[uint32(wgDetails.Interface.SwIfIndex)]
   109  		if !ifIdxExists {
   110  			h.log.Warnf("Wireguard interface dump: interface name for index %d not found", wgDetails.Interface.SwIfIndex)
   111  			continue
   112  		}
   113  
   114  		wgLink := &interfaces.WireguardLink{
   115  			Port:         uint32(wgDetails.Interface.Port),
   116  		}
   117  		wgLink.PrivateKey = base64.StdEncoding.EncodeToString(wgDetails.Interface.PrivateKey)
   118  
   119  		srcAddr := wgDetails.Interface.SrcIP.ToIP()
   120  		if !srcAddr.IsUnspecified() {
   121  			wgLink.SrcAddr = srcAddr.String()
   122  		}
   123  
   124  		ifc[uint32(wgDetails.Interface.SwIfIndex)].Interface.Link = &interfaces.Interface_Wireguard { Wireguard: wgLink }
   125  		ifc[uint32(wgDetails.Interface.SwIfIndex)].Interface.Type = interfaces.Interface_WIREGUARD_TUNNEL
   126  	}
   127  	return nil
   128  }