Skip to content

Commit

Permalink
Change xconnect to bridge domain in case of remote vlan
Browse files Browse the repository at this point in the history
Signed-off-by: Laszlo Kiraly <laszlo.kiraly@est.tech>
  • Loading branch information
ljkiraly committed Nov 15, 2022
1 parent 9189e80 commit 1e143db
Show file tree
Hide file tree
Showing 14 changed files with 502 additions and 229 deletions.
2 changes: 2 additions & 0 deletions pkg/networkservice/chains/forwarder/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import (
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/tag"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/up"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/xconnect"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/xconnect/l2bridgedomain"
)

// Connection aggregates the api.Connection and api.ChannelProvider interfaces
Expand Down Expand Up @@ -111,6 +112,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn
stats.NewServer(ctx, opts.statsOpts...),
up.NewServer(ctx, vppConn),
xconnect.NewServer(vppConn),
l2bridgedomain.NewServer(vppConn),
connectioncontextkernel.NewServer(),
ethernetcontext.NewVFServer(),
tag.NewServer(ctx, vppConn),
Expand Down
4 changes: 1 addition & 3 deletions pkg/networkservice/mechanisms/vlan/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
"github.com/networkservicemesh/sdk/pkg/tools/postpone"

"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vlan/hwaddress"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vlan/l2vtr"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vlan/mtu"
)
Expand All @@ -49,7 +48,6 @@ type vlanClient struct {
// NewClient returns a VLAN client chain element
func NewClient(vppConn api.Connection, domain2Device map[string]string) networkservice.NetworkServiceClient {
return chain.NewNetworkServiceClient(
hwaddress.NewClient(vppConn),
mtu.NewClient(vppConn),
l2vtr.NewClient(vppConn),
&vlanClient{
Expand Down Expand Up @@ -89,6 +87,6 @@ func (v *vlanClient) Request(ctx context.Context, request *networkservice.Networ
}

func (v *vlanClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) {
_ = delSubIf(ctx, conn, v.vppConn)
delSubIf(ctx, conn)
return next.Client(ctx).Close(ctx, conn, opts...)
}
117 changes: 57 additions & 60 deletions pkg/networkservice/mechanisms/vlan/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package vlan
import (
"context"
"io"
"strings"
"time"

"git.fd.io/govpp.git/api"
Expand Down Expand Up @@ -49,57 +50,69 @@ func addSubIf(ctx context.Context, conn *networkservice.Connection, vppConn api.
if !ok {
return errors.Errorf("no interface name for label %s", via)
}

now := time.Now()
client, err := interfaces.NewServiceClient(vppConn).SwInterfaceDump(ctx, &interfaces.SwInterfaceDump{
NameFilterValid: true,
NameFilter: hostIFName,
})
vlanID := mechanism.GetVlanID()
hostSwIfIndex, vlanSwIfIndex, err := getHostOrVlanInterface(ctx, vppConn, hostIFName, vlanID)
if err != nil {
return errors.Wrapf(err, "error attempting to get interface dump client to set vlan subinterface on %q", hostIFName)
return err
}
log.FromContext(ctx).
WithField("duration", time.Since(now)).
WithField("HostInterfaceName", hostIFName).
WithField("vppapi", "SwInterfaceDump").Debug("completed")

for {
details, err := client.Recv()
if err == io.EOF {
break
}
if err != nil {
return errors.Wrapf(err, "error attempting to get interface details to set vlan subinterface on %q", hostIFName)
}

if (hostIFName != details.InterfaceName) && (afPacketNamePrefix+hostIFName != details.InterfaceName) {
if vlanID != 0 {
if vlanSwIfIndex != 0 {
log.FromContext(ctx).
WithField("InterfaceName", details.InterfaceName).
WithField("vppapi", "SwInterfaceDetails").Debug("skipped")
continue
}

swIfIndex := details.SwIfIndex
vlanID := mechanism.GetVlanID()
if vlanID != 0 {
vlanIfIndex, shouldReturn, returnValue := vppAddSubIf(ctx, vppConn, swIfIndex, vlanID)
WithField("VlanInterfaceIndex", vlanSwIfIndex).Debug("Vlan Interface already created")
ifindex.Store(ctx, true, vlanSwIfIndex)
} else {
newVlanIfIndex, shouldReturn, returnValue := vppAddSubIf(ctx, vppConn, hostSwIfIndex, vlanID)
if shouldReturn {
return returnValue
}
ifindex.Store(ctx, true, *vlanIfIndex)
} else {
log.FromContext(ctx).
WithField("HostInterfaceIndex", swIfIndex).
WithField("Details", details).Debug("QinQ disabled")
ifindex.Store(ctx, true, swIfIndex)
ifindex.Store(ctx, true, *newVlanIfIndex)
}
return nil
} else {
log.FromContext(ctx).
WithField("HostInterfaceIndex", hostSwIfIndex).Debug("QinQ disabled")
ifindex.Store(ctx, true, hostSwIfIndex)
}
return errors.Errorf("no interface name found %s", hostIFName)
/* Store vlanID used by bridge domain server */
Store(ctx, true, vlanID)
}
return nil
}

func getHostOrVlanInterface(ctx context.Context, vppConn api.Connection, hostIFName string, vlanID uint32) (hostSwIfIndex, vlanSwIfIndex interface_types.InterfaceIndex, err error) {
now := time.Now()
client, err := interfaces.NewServiceClient(vppConn).SwInterfaceDump(ctx, &interfaces.SwInterfaceDump{
NameFilterValid: true,
NameFilter: hostIFName,
})
if err != nil {
return 0, 0, errors.Wrapf(err, "error attempting to get interface dump client to set vlan subinterface on %q", hostIFName)
}
log.FromContext(ctx).
WithField("duration", time.Since(now)).
WithField("HostInterfaceName", hostIFName).
WithField("vppapi", "SwInterfaceDump").Debug("completed")
for {
details, err := client.Recv()
if err == io.EOF {
break
}
if err != nil {
return 0, 0, errors.Wrapf(err, "error attempting to get interface details to set vlan subinterface on %q", hostIFName)
}
if (vlanID != 0) && strings.Contains(details.InterfaceName, hostIFName) && (details.Type == interface_types.IF_API_TYPE_SUB) && (details.SubID == vlanID) {
return 0, details.SwIfIndex, nil
}
if (hostIFName == details.InterfaceName) || (afPacketNamePrefix+hostIFName == details.InterfaceName) {
hostSwIfIndex = details.SwIfIndex
}
}

if hostSwIfIndex == 0 {
return 0, 0, errors.Errorf("no interface name found %s", hostIFName)
}
return hostSwIfIndex, 0, nil
}

func vppAddSubIf(ctx context.Context, vppConn api.Connection, swIfIndex interface_types.InterfaceIndex, vlanID uint32) (*interface_types.InterfaceIndex, bool, error) {
now := time.Now()
vlanSubif := &interfaces.CreateVlanSubif{
Expand All @@ -119,30 +132,14 @@ func vppAddSubIf(ctx context.Context, vppConn api.Connection, swIfIndex interfac
WithField("vppapi", "CreateVlanSubIf").Debug("completed")
return &rsp.SwIfIndex, false, nil
}
func delSubIf(ctx context.Context, conn *networkservice.Connection, vppConn api.Connection) error {
func delSubIf(ctx context.Context, conn *networkservice.Connection) {
if mechanism := vlanmech.ToMechanism(conn.GetMechanism()); mechanism != nil {
swIfIndex, ok := ifindex.Load(ctx, true)
_, ok := ifindex.Load(ctx, true)
if !ok {
return nil
}

if mechanism.GetVlanID() == 0 {
ifindex.Delete(ctx, true)
return nil
return
}
now := time.Now()
vlanSubif := &interfaces.DeleteSubif{
SwIfIndex: swIfIndex,
}
_, err := interfaces.NewServiceClient(vppConn).DeleteSubif(ctx, vlanSubif)
if err != nil {
return errors.WithStack(err)
}
log.FromContext(ctx).
WithField("duration", time.Since(now)).
WithField("HostInterfaceIndex", swIfIndex).
WithField("vppapi", "DeleteSubif").Debug("completed")
/* Delete sub-interface together with the l2 bridge */
ifindex.Delete(ctx, true)
Delete(ctx, true)
}
return nil
}
72 changes: 0 additions & 72 deletions pkg/networkservice/mechanisms/vlan/hwaddress/client.go

This file was deleted.

64 changes: 0 additions & 64 deletions pkg/networkservice/mechanisms/vlan/hwaddress/common.go

This file was deleted.

1 change: 0 additions & 1 deletion pkg/networkservice/mechanisms/vlan/l2vtr/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,5 @@ func (v *l2vtrClient) Request(ctx context.Context, request *networkservice.Netwo
}

func (v *l2vtrClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) {
_ = disableVtr(ctx, conn, v.vppConn)
return next.Client(ctx).Close(ctx, conn, opts...)
}
26 changes: 0 additions & 26 deletions pkg/networkservice/mechanisms/vlan/l2vtr/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,3 @@ func enableVtr(ctx context.Context, conn *networkservice.Connection, vppConn api
}
return nil
}

func disableVtr(ctx context.Context, conn *networkservice.Connection, vppConn api.Connection) error {
if mechanism := vlanmech.ToMechanism(conn.GetMechanism()); mechanism != nil {
if mechanism.GetVlanID() == 0 {
return nil
}
swIfIndex, ok := ifindex.Load(ctx, true)
if !ok {
return nil
}
now := time.Now()

if _, err := l2.NewServiceClient(vppConn).L2InterfaceVlanTagRewrite(ctx, &l2.L2InterfaceVlanTagRewrite{
SwIfIndex: swIfIndex,
VtrOp: L2VtrDisabled,
}); err != nil {
return errors.WithStack(err)
}
log.FromContext(ctx).
WithField("duration", time.Since(now)).
WithField("SwIfIndex", swIfIndex).
WithField("operation", "DISABLE").
WithField("vppapi", "L2InterfaceVlanTagRewrite").Debug("completed")
}
return nil
}
Loading

0 comments on commit 1e143db

Please sign in to comment.