go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/vppcalls/vpp2210/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 vpp2210
    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/vpp2210/interface_types"
    24  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2210/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 invalidIdx, 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  	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  	// index of ^uint32(0) dumps all interfaces
    98  	req := &wireguard.WireguardInterfaceDump{
    99  		SwIfIndex: interface_types.InterfaceIndex(^uint32(0)),
   100  	}
   101  	reqCtx := h.callsChannel.SendMultiRequest(req)
   102  
   103  	for {
   104  		wgDetails := &wireguard.WireguardInterfaceDetails{}
   105  		stop, err := reqCtx.ReceiveReply(wgDetails)
   106  		if stop {
   107  			break // break from the loop
   108  		}
   109  		if err != nil {
   110  			return fmt.Errorf("failed to dump wireguard interface details: %v", err)
   111  		}
   112  		_, ifIdxExists := ifc[uint32(wgDetails.Interface.SwIfIndex)]
   113  		if !ifIdxExists {
   114  			h.log.Warnf("Wireguard interface dump: interface name for index %d not found", wgDetails.Interface.SwIfIndex)
   115  			continue
   116  		}
   117  
   118  		wgLink := &interfaces.WireguardLink{
   119  			Port: uint32(wgDetails.Interface.Port),
   120  		}
   121  		wgLink.PrivateKey = base64.StdEncoding.EncodeToString(wgDetails.Interface.PrivateKey)
   122  
   123  		srcAddr := wgDetails.Interface.SrcIP.ToIP()
   124  		if !srcAddr.IsUnspecified() {
   125  			wgLink.SrcAddr = srcAddr.String()
   126  		}
   127  
   128  		ifc[uint32(wgDetails.Interface.SwIfIndex)].Interface.Link = &interfaces.Interface_Wireguard{Wireguard: wgLink}
   129  		ifc[uint32(wgDetails.Interface.SwIfIndex)].Interface.Type = interfaces.Interface_WIREGUARD_TUNNEL
   130  	}
   131  	return nil
   132  }