Skip to content

Commit

Permalink
Pseudo-random MACs & Node.Endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
networkop committed May 15, 2021
1 parent 633951e commit 5e40e5e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 18 deletions.
10 changes: 9 additions & 1 deletion clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const (
hostNSPath = "__host"
// veth link mtu. jacked up to 65k to allow jumbo testing of various sizes
defaultVethLinkMTU = 65000
// containerlab's reserved OUI
clabOUI = "aa:c1:ab"
)

// supported kinds
Expand Down Expand Up @@ -368,6 +370,7 @@ func (c *CLab) NewNode(nodeName string, nodeCfg NodeConfig, idx int) error {
node.Fqdn = nodeName + "." + c.Config.Name + ".io"
node.LabDir = c.Dir.Lab + "/" + nodeName
node.Index = idx
node.Endpoints = []*types.Endpoint{}

node.NetworkMode = strings.ToLower(nodeCfg.NetworkMode)

Expand Down Expand Up @@ -513,6 +516,10 @@ func (c *CLab) NewEndpoint(e string) *types.Endpoint {
}
nName := split[0] // node name
epName := split[1] // endpoint name

// generate unqiue MAC
endpoint.MAC = genMac(clabOUI)

// search the node pointer for a node name referenced in endpoint section
switch nName {
// "host" is a special reference to host namespace
Expand All @@ -532,8 +539,9 @@ func (c *CLab) NewEndpoint(e string) *types.Endpoint {
}
default:
for name, n := range c.Nodes {
if name == split[0] {
if name == nName {
endpoint.Node = n
n.Endpoints = append(n.Endpoints, endpoint)
break
}
}
Expand Down
24 changes: 18 additions & 6 deletions clab/netlink.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,18 @@ func (c *CLab) CreateVirtualWiring(l *types.Link) (err error) {
BRndmName = l.B.EndpointName
}

// Generate MAC addresses
aMAC, err := net.ParseMAC(l.A.MAC)
if err != nil {
return err
}
bMAC, err := net.ParseMAC(l.B.MAC)
if err != nil {
return err
}

// create veth pair in the root netns
vA.Link, vB.Link, err = createVethIface(ARndmName, BRndmName, l.MTU)
vA.Link, vB.Link, err = createVethIface(ARndmName, BRndmName, l.MTU, aMAC, bMAC)
if err != nil {
return err
}
Expand All @@ -108,14 +118,16 @@ func (c *CLab) CreateVirtualWiring(l *types.Link) (err error) {

// createVethIface takes two veth endpoint structs and create a veth pair and return
// veth interface links.
func createVethIface(ifName, peerName string, mtu int) (linkA netlink.Link, linkB netlink.Link, err error) {
func createVethIface(ifName, peerName string, mtu int, aMAC, bMAC net.HardwareAddr) (linkA netlink.Link, linkB netlink.Link, err error) {
linkA = &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{
Name: ifName,
Flags: net.FlagUp,
MTU: mtu,
Name: ifName,
HardwareAddr: aMAC,
Flags: net.FlagUp,
MTU: mtu,
},
PeerName: peerName,
PeerName: peerName,
PeerHardwareAddr: bMAC,
}

if err := netlink.LinkAdd(linkA); err != nil {
Expand Down
45 changes: 34 additions & 11 deletions cmd/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func init() {
destroyCmd.Flags().BoolVarP(&cleanup, "cleanup", "", false, "delete lab directory")
destroyCmd.Flags().BoolVarP(&graceful, "graceful", "", false, "attempt to stop containers before removing")
destroyCmd.Flags().BoolVarP(&all, "all", "a", false, "destroy all containerlab labs")
destroyCmd.Flags().UintVarP(&maxWorkers, "max-workers", "", 0, "limit the maximum number of workers deleteing nodes")
}

func deleteEntriesFromHostsFile(containers []types.GenericContainer, bridgeName string) error {
Expand Down Expand Up @@ -181,22 +182,44 @@ func destroyLab(ctx context.Context, c *clab.CLab) (err error) {
labDir = filepath.Dir(containers[0].Labels["clab-node-lab-dir"])
}

if maxWorkers == 0 {
maxWorkers = uint(len(containers))
}

log.Infof("Destroying container lab: %s", c.Config.Name)
ctrChan := make(chan *types.GenericContainer)
wg := new(sync.WaitGroup)
wg.Add(len(containers))
for _, cont := range containers {
go func(cont types.GenericContainer) {
wg.Add(int(maxWorkers))
for i := uint(0); i < maxWorkers; i++ {

go func(i uint) {
defer wg.Done()
name := cont.ID
if len(cont.Names) > 0 {
name = strings.TrimLeft(cont.Names[0], "/")
}
err := c.Runtime.DeleteContainer(ctx, name)
if err != nil {
log.Errorf("could not remove container '%s': %v", name, err)
for {
select {
case cont := <-ctrChan:
if cont == nil {
log.Debugf("Worker %d terminating...", i)
return
}
name := cont.ID
if len(cont.Names) > 0 {
name = strings.TrimLeft(cont.Names[0], "/")
}
err := c.Runtime.DeleteContainer(ctx, name)
if err != nil {
log.Errorf("could not remove container '%s': %v", name, err)
}
case <-ctx.Done():
return
}
}
}(cont)
}(i)
}
for _, ctr := range containers {
ctrChan <- &ctr
}
close(ctrChan)

wg.Wait()

// remove the lab directories
Expand Down
4 changes: 4 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type Endpoint struct {
Node *Node
// e1-x, eth, etc
EndpointName string
// mac address
MAC string
}

// mgmtNet struct defines the management network options
Expand Down Expand Up @@ -77,6 +79,8 @@ type Node struct {
Publish []string //list of ports to publish with mysocketctl
// container labels
Labels map[string]string
// Slice of pointers to local endpoints
Endpoints []*Endpoint
}

// GenerateConfig generates configuration for the nodes
Expand Down

0 comments on commit 5e40e5e

Please sign in to comment.