Skip to content

Commit

Permalink
refactor(svi): move netlink to a separate file
Browse files Browse the repository at this point in the history
Signed-off-by: Boris Glimcher <[email protected]>
  • Loading branch information
glimchb committed Oct 17, 2023
1 parent 5712570 commit 38f466d
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 54 deletions.
57 changes: 3 additions & 54 deletions pkg/evpn/svi.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,12 @@ package evpn

import (
"context"
"encoding/binary"
"fmt"
"log"
"net"
"path"
"sort"

"github.com/google/uuid"
"github.com/vishvananda/netlink"

pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go"

Expand Down Expand Up @@ -63,62 +60,14 @@ func (s *Server) CreateSvi(ctx context.Context, in *pb.CreateSviRequest) (*pb.Sv
err := status.Errorf(codes.NotFound, "unable to find key %s", in.Svi.Spec.Vrf)
return nil, err
}
// not found, so create a new one
bridge, err := s.nLink.LinkByName(ctx, tenantbridgeName)
if err != nil {
err := status.Errorf(codes.NotFound, "unable to find key %s", tenantbridgeName)
// configure netlink
if err := s.netlinkCreateSvi(ctx, in, bridgeObject, vrf); err != nil {
return nil, err
}
// configure FRR
vid := uint16(bridgeObject.Spec.VlanId)
// Example: bridge vlan add dev br-tenant vid <vlan-id> self
if err := s.nLink.BridgeVlanAdd(ctx, bridge, vid, false, false, true, false); err != nil {
fmt.Printf("Failed to add vlan to bridge: %v", err)
return nil, err
}
// Example: ip link add link br-tenant name <link_svi> type vlan id <vlan-id>
vlanName := fmt.Sprintf("vlan%d", vid)
vlandev := &netlink.Vlan{LinkAttrs: netlink.LinkAttrs{Name: vlanName, ParentIndex: bridge.Attrs().Index}, VlanId: int(vid)}
log.Printf("Creating VLAN %v", vlandev)
if err := s.nLink.LinkAdd(ctx, vlandev); err != nil {
fmt.Printf("Failed to create vlan link: %v", err)
return nil, err
}
// Example: ip link set <link_svi> addr aa:bb:cc:00:00:41
if len(in.Svi.Spec.MacAddress) > 0 {
if err := s.nLink.LinkSetHardwareAddr(ctx, vlandev, in.Svi.Spec.MacAddress); err != nil {
fmt.Printf("Failed to set MAC on link: %v", err)
return nil, err
}
}
// Example: ip address add <svi-ip-with prefixlength> dev <link_svi>
for _, gwip := range in.Svi.Spec.GwIpPrefix {
fmt.Printf("Assign the GW IP address %v to the SVI interface %v", gwip, vlandev)
myip := make(net.IP, 4)
binary.BigEndian.PutUint32(myip, gwip.Addr.GetV4Addr())
addr := &netlink.Addr{IPNet: &net.IPNet{IP: myip, Mask: net.CIDRMask(int(gwip.Len), 32)}}
if err := s.nLink.AddrAdd(ctx, vlandev, addr); err != nil {
fmt.Printf("Failed to set IP on link: %v", err)
return nil, err
}
}
// get net device by name
vrfName := path.Base(vrf.Name)
vrfdev, err := s.nLink.LinkByName(ctx, vrfName)
if err != nil {
err := status.Errorf(codes.NotFound, "unable to find key %s", vrf.Name)
return nil, err
}
// Example: ip link set <link_svi> master <vrf-name> up
if err := s.nLink.LinkSetMaster(ctx, vlandev, vrfdev); err != nil {
fmt.Printf("Failed to add vlandev to vrf: %v", err)
return nil, err
}
// Example: ip link set <link_svi> up
if err := s.nLink.LinkSetUp(ctx, vlandev); err != nil {
fmt.Printf("Failed to up link: %v", err)
return nil, err
}
// configure FRR
if err := s.frrCreateSviRequest(ctx, in, vrfName, vlanName); err != nil {
return nil, err
}
Expand Down
80 changes: 80 additions & 0 deletions pkg/evpn/svi_netlink.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries.
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.

// Package evpn is the main package of the application
package evpn

import (
"context"
"encoding/binary"
"fmt"
"log"
"net"
"path"

"github.com/vishvananda/netlink"

pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (s *Server) netlinkCreateSvi(ctx context.Context, in *pb.CreateSviRequest, bridgeObject *pb.LogicalBridge, vrf *pb.Vrf) error {
bridge, err := s.nLink.LinkByName(ctx, tenantbridgeName)
if err != nil {
err := status.Errorf(codes.NotFound, "unable to find key %s", tenantbridgeName)
return err
}
vid := uint16(bridgeObject.Spec.VlanId)
// Example: bridge vlan add dev br-tenant vid <vlan-id> self
if err := s.nLink.BridgeVlanAdd(ctx, bridge, vid, false, false, true, false); err != nil {
fmt.Printf("Failed to add vlan to bridge: %v", err)
return err
}
// Example: ip link add link br-tenant name <link_svi> type vlan id <vlan-id>
vlanName := fmt.Sprintf("vlan%d", vid)
vlandev := &netlink.Vlan{LinkAttrs: netlink.LinkAttrs{Name: vlanName, ParentIndex: bridge.Attrs().Index}, VlanId: int(vid)}
log.Printf("Creating VLAN %v", vlandev)
if err := s.nLink.LinkAdd(ctx, vlandev); err != nil {
fmt.Printf("Failed to create vlan link: %v", err)
return err
}
// Example: ip link set <link_svi> addr aa:bb:cc:00:00:41
if len(in.Svi.Spec.MacAddress) > 0 {
if err := s.nLink.LinkSetHardwareAddr(ctx, vlandev, in.Svi.Spec.MacAddress); err != nil {
fmt.Printf("Failed to set MAC on link: %v", err)
return err
}
}
// Example: ip address add <svi-ip-with prefixlength> dev <link_svi>
for _, gwip := range in.Svi.Spec.GwIpPrefix {
fmt.Printf("Assign the GW IP address %v to the SVI interface %v", gwip, vlandev)
myip := make(net.IP, 4)
binary.BigEndian.PutUint32(myip, gwip.Addr.GetV4Addr())
addr := &netlink.Addr{IPNet: &net.IPNet{IP: myip, Mask: net.CIDRMask(int(gwip.Len), 32)}}
if err := s.nLink.AddrAdd(ctx, vlandev, addr); err != nil {
fmt.Printf("Failed to set IP on link: %v", err)
return err
}
}
// get net device by name
vrfName := path.Base(vrf.Name)
vrfdev, err := s.nLink.LinkByName(ctx, vrfName)
if err != nil {
err := status.Errorf(codes.NotFound, "unable to find key %s", vrf.Name)
return err
}
// Example: ip link set <link_svi> master <vrf-name> up
if err := s.nLink.LinkSetMaster(ctx, vlandev, vrfdev); err != nil {
fmt.Printf("Failed to add vlandev to vrf: %v", err)
return err
}
// Example: ip link set <link_svi> up
if err := s.nLink.LinkSetUp(ctx, vlandev); err != nil {
fmt.Printf("Failed to up link: %v", err)
return err
}
return nil
}

0 comments on commit 38f466d

Please sign in to comment.