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

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