Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(svi): move netlink to a separate file #261

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
Loading