-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change xconnect to bridge domain in case of remote vlan
Signed-off-by: Laszlo Kiraly <laszlo.kiraly@est.tech>
- Loading branch information
Showing
11 changed files
with
452 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
// Copyright (c) 2022 Nordix Foundation. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package l2bridgedomain | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"git.fd.io/govpp.git/api" | ||
"github.com/edwarnicke/govpp/binapi/interface_types" | ||
"github.com/edwarnicke/govpp/binapi/l2" | ||
"github.com/pkg/errors" | ||
|
||
"github.com/networkservicemesh/sdk/pkg/tools/log" | ||
|
||
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vlan" | ||
"github.com/networkservicemesh/sdk-vpp/pkg/tools/ifindex" | ||
) | ||
|
||
type bridgeDomain struct { | ||
/* BdID */ | ||
id uint32 | ||
|
||
/* attached - attached interfaces */ | ||
attached map[interface_types.InterfaceIndex]struct{} | ||
} | ||
|
||
type bridgeDomainKey struct { | ||
vlanID uint32 | ||
clientIfIndex interface_types.InterfaceIndex | ||
} | ||
|
||
func addBridgeDomain(ctx context.Context, vppConn api.Connection, bridges *l2BridgeDomain) error { | ||
vlanID, ok := vlan.Load(ctx, true) | ||
if !ok { | ||
return nil | ||
} | ||
clientIfIndex, ok := ifindex.Load(ctx, true) | ||
if !ok { | ||
return nil | ||
} | ||
serverIfIndex, ok := ifindex.Load(ctx, false) | ||
if !ok { | ||
return nil | ||
} | ||
|
||
// key <vlanID, clientIfIndex> to handle the vlanID == 0 case | ||
key := bridgeDomainKey{ | ||
vlanID: vlanID, | ||
clientIfIndex: clientIfIndex, | ||
} | ||
l2Bridge, ok := bridges.Load(key) | ||
if !ok { | ||
bridgeID, err := addDelVppBridgeDomain(ctx, vppConn, ^uint32(0), true) | ||
if err != nil { | ||
return err | ||
} | ||
l2Bridge = &bridgeDomain{ | ||
id: bridgeID, | ||
attached: make(map[interface_types.InterfaceIndex]struct{}), | ||
} | ||
bridges.Store(key, l2Bridge) | ||
} | ||
if _, ok = l2Bridge.attached[serverIfIndex]; !ok { | ||
err := addDelVppInterfaceBridgeDomain(ctx, vppConn, serverIfIndex, l2Bridge.id, 1, true) | ||
if err != nil { | ||
return err | ||
} | ||
l2Bridge.attached[serverIfIndex] = struct{}{} | ||
bridges.Store(key, l2Bridge) | ||
} | ||
if _, ok = l2Bridge.attached[clientIfIndex]; !ok { | ||
err := addDelVppInterfaceBridgeDomain(ctx, vppConn, clientIfIndex, l2Bridge.id, 0, true) | ||
if err != nil { | ||
return err | ||
} | ||
l2Bridge.attached[clientIfIndex] = struct{}{} | ||
bridges.Store(key, l2Bridge) | ||
} | ||
return nil | ||
} | ||
|
||
func delBridgeDomain(ctx context.Context, vppConn api.Connection, bridges *l2BridgeDomain) error { | ||
if vlanID, ok := vlan.Load(ctx, true); ok { | ||
if clientIfIndex, ok := ifindex.Load(ctx, true); ok { | ||
key := bridgeDomainKey{ | ||
vlanID: vlanID, | ||
clientIfIndex: clientIfIndex, | ||
} | ||
l2Bridge, ok := bridges.Load(key) | ||
if !ok { | ||
return nil | ||
} | ||
if serverIfIndex, okey := ifindex.Load(ctx, false); okey { | ||
if _, ok = l2Bridge.attached[serverIfIndex]; ok { | ||
err := addDelVppInterfaceBridgeDomain(ctx, vppConn, serverIfIndex, l2Bridge.id, 0, false) | ||
if err != nil { | ||
return err | ||
} | ||
delete(l2Bridge.attached, serverIfIndex) | ||
} | ||
} | ||
if len(l2Bridge.attached) == 1 { | ||
// last interface -> delete the bridge also | ||
if _, ok = l2Bridge.attached[clientIfIndex]; ok { | ||
err := addDelVppInterfaceBridgeDomain(ctx, vppConn, clientIfIndex, l2Bridge.id, 0, false) | ||
if err != nil { | ||
return err | ||
} | ||
delete(l2Bridge.attached, clientIfIndex) | ||
_, err = addDelVppBridgeDomain(ctx, vppConn, l2Bridge.id, false) | ||
if err != nil { | ||
return err | ||
} | ||
bridges.Delete(key) | ||
} | ||
} else { | ||
bridges.Store(key, l2Bridge) | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func addDelVppBridgeDomain(ctx context.Context, vppConn api.Connection, bridgeID uint32, isAdd bool) (uint32, error) { | ||
now := time.Now() | ||
bridgeDomainAddDelV2 := &l2.BridgeDomainAddDelV2{ | ||
IsAdd: isAdd, | ||
BdID: bridgeID, | ||
Flood: true, | ||
Forward: true, | ||
Learn: true, | ||
UuFlood: true, | ||
} | ||
rsp, err := l2.NewServiceClient(vppConn).BridgeDomainAddDelV2(ctx, bridgeDomainAddDelV2) | ||
if err != nil { | ||
return 0, errors.WithStack(err) | ||
} | ||
log.FromContext(ctx). | ||
WithField("bridgeID", rsp.BdID). | ||
WithField("isAdd", isAdd). | ||
WithField("duration", time.Since(now)). | ||
WithField("vppConn", vppConn). | ||
WithField("vppapi", "addDelVppBridgeDomain").Info("completed") | ||
return rsp.BdID, nil | ||
} | ||
|
||
func addDelVppInterfaceBridgeDomain(ctx context.Context, vppConn api.Connection, swIfIndex interface_types.InterfaceIndex, bridgeID uint32, shg uint8, isAdd bool) error { | ||
now := time.Now() | ||
_, err := l2.NewServiceClient(vppConn).SwInterfaceSetL2Bridge(ctx, &l2.SwInterfaceSetL2Bridge{ | ||
RxSwIfIndex: swIfIndex, | ||
Enable: isAdd, | ||
BdID: bridgeID, | ||
Shg: shg, | ||
}) | ||
if err != nil { | ||
return errors.WithStack(err) | ||
} | ||
log.FromContext(ctx). | ||
WithField("swIfIndex", swIfIndex). | ||
WithField("bridgeID", bridgeID). | ||
WithField("isAdd", isAdd). | ||
WithField("shg", shg). | ||
WithField("duration", time.Since(now)). | ||
WithField("vppConn", vppConn). | ||
WithField("vppapi", "addDelVppInterfaceBridgeDomain").Info("completed") | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright (c) 2022 Nordix Foundation. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Package l2bridgedomain provides chain elements for creating l2 bridge domain in vpp and adding client and server interfaces (if present) | ||
package l2bridgedomain |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright (c) 2022 Nordix Foundation. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package l2bridgedomain | ||
|
||
import ( | ||
"sync" | ||
) | ||
|
||
//go:generate go-syncmap -output l2_bridge_domain_map.gen.go -type l2BridgeDomain<bridgeDomainKey,*bridgeDomain> | ||
|
||
// l2BridgeDomain - sync.Map storing *bridgeDomain values to bridgeDomainKey(VLAN-ID, clientIfIndex) | ||
type l2BridgeDomain sync.Map |
73 changes: 73 additions & 0 deletions
73
pkg/networkservice/l2bridgedomain/l2_bridge_domain_map.gen.go
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.