Skip to content

Commit 60842e7

Browse files
committed
Correctly derive vlans required for vxlan networks
- take the allocated global vlans and vlans for vxlan networks for all tenants into consideration for deriving the vlans required for next vxlan network. - also added a cli to dump the resource config state
1 parent d90fa5c commit 60842e7

File tree

3 files changed

+116
-31
lines changed

3 files changed

+116
-31
lines changed

examples/two_hosts_multiple_tenants_mix_vlan_vxlan.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"DefaultNetType" : "vxlan",
3434
"SubnetPool" : "11.1.0.0/16",
3535
"AllocSubnetLen" : 24,
36-
"Vxlans" : "10001-14000",
36+
"Vxlans" : "10001-12000",
3737
"Networks" : [{
3838
"Name" : "purple",
3939
"Endpoints" : [{

gstate/gstate.go

+62-16
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,48 @@ func (g *Oper) Clear() error {
163163
return g.StateDriver.ClearState(key)
164164
}
165165

166+
// The following function derives the number of available vlan tags.
167+
// XXX: Since it is run at netmaster, it is guaranteed to have a consistent view of
168+
// resource usage. Revisit if this assumption changes, as then it might need to
169+
// be moved to resource-manager
170+
func deriveAvailableVlans(stateDriver core.StateDriver) (*bitset.BitSet, error) {
171+
// available vlans = vlan-space - For each tenant (vlans + local-vxlan-vlans)
172+
availableVlans := netutils.CreateBitset(12)
173+
174+
// get all vlans
175+
readVlanRsrc := &resources.AutoVlanCfgResource{}
176+
readVlanRsrc.StateDriver = stateDriver
177+
vlanRsrcs, err := readVlanRsrc.ReadAll()
178+
if core.ErrIfKeyExists(err) != nil {
179+
return nil, err
180+
} else if err != nil {
181+
vlanRsrcs = []core.State{}
182+
}
183+
for _, rsrc := range vlanRsrcs {
184+
cfg := rsrc.(*resources.AutoVlanCfgResource)
185+
availableVlans = availableVlans.Union(cfg.Vlans)
186+
}
187+
188+
//get all vxlan-vlans
189+
readVxlanRsrc := &resources.AutoVxlanCfgResource{}
190+
readVxlanRsrc.StateDriver = stateDriver
191+
vxlanRsrcs, err := readVxlanRsrc.ReadAll()
192+
if core.ErrIfKeyExists(err) != nil {
193+
return nil, err
194+
} else if err != nil {
195+
vxlanRsrcs = []core.State{}
196+
}
197+
for _, rsrc := range vxlanRsrcs {
198+
cfg := rsrc.(*resources.AutoVxlanCfgResource)
199+
availableVlans = availableVlans.Union(cfg.LocalVlans)
200+
}
201+
202+
// subtract to get availableVlans
203+
availableVlans = availableVlans.Complement()
204+
clearReservedVlans(availableVlans)
205+
return availableVlans, nil
206+
}
207+
166208
func (gc *Cfg) initVxlanBitset(vxlans string) (*resources.AutoVxlanCfgResource,
167209
uint, error) {
168210

@@ -182,26 +224,30 @@ func (gc *Cfg) initVxlanBitset(vxlans string) (*resources.AutoVxlanCfgResource,
182224
vxlanRsrcCfg.Vxlans.Set(uint(vxlan - vxlanRange.Min))
183225
}
184226

185-
// XXX: we should derive free-vlans by looking at all tenants,
186-
// instead of just one.
187-
vlanRsrcCfg := &resources.AutoVlanCfgResource{}
188-
vlanRsrcCfg.StateDriver = gc.StateDriver
189-
err = vlanRsrcCfg.Read(gc.Tenant)
190-
if core.ErrIfKeyExists(err) != nil {
227+
availableVlans, err := deriveAvailableVlans(gc.StateDriver)
228+
if err != nil {
191229
return nil, 0, err
192-
} else if err != nil {
193-
// a vlan resource has not been defined, assume entire space available
194-
// for vxlan.
195-
vlanRsrcCfg.Vlans = netutils.CreateBitset(12)
196-
vlanRsrcCfg.Vlans.ClearAll()
197230
}
198-
// available vlans are the ones that are configured to be not consumed by
199-
// vlan networks
200-
availableVlans := vlanRsrcCfg.Vlans.Complement()
201-
clearReservedVlans(availableVlans)
202-
if count := availableVlans.Count(); int(count) < vxlanRange.Max-vxlanRange.Min {
231+
232+
localVlansReqd := vxlanRange.Max - vxlanRange.Min + 1
233+
if count := availableVlans.Count(); int(count) < localVlansReqd {
203234
return nil, 0, &core.Error{Desc: fmt.Sprintf("Available free local vlans (%d) is less than possible vxlans (%d)",
204235
count, vxlanRange.Max-vxlanRange.Min)}
236+
} else if int(count) > localVlansReqd {
237+
//only reserve the #vxlan amount of bits
238+
var clearBitMarker uint = 0
239+
for i := 0; i < localVlansReqd; i++ {
240+
clearBitMarker, _ = availableVlans.NextSet(clearBitMarker)
241+
clearBitMarker += 1
242+
}
243+
clearBitMarker += 1
244+
for {
245+
if bit, ok := availableVlans.NextSet(clearBitMarker); ok {
246+
availableVlans.Clear(bit)
247+
} else {
248+
break
249+
}
250+
}
205251
}
206252

207253
vxlanRsrcCfg.LocalVlans = availableVlans

netdcli/netdcli.go

+53-14
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,32 @@ import (
2828
"github.com/contiv/netplugin/drivers"
2929
"github.com/contiv/netplugin/gstate"
3030
"github.com/contiv/netplugin/netutils"
31+
"github.com/contiv/netplugin/resources"
3132
)
3233

3334
const (
34-
CLI_CONSTRUCT_GLOBAL = "global"
35-
CLI_CONSTRUCT_NW = "network"
36-
CLI_CONSTRUCT_EP = "endpoint"
37-
CLI_OPER_GET = "get"
38-
CLI_OPER_CREATE = "create"
39-
CLI_OPER_DELETE = "delete"
40-
CLI_OPER_ATTACH = "attach"
41-
CLI_OPER_DETACH = "detach"
35+
CLI_CONSTRUCT_GLOBAL = "global"
36+
CLI_CONSTRUCT_NW = "network"
37+
CLI_CONSTRUCT_EP = "endpoint"
38+
CLI_CONSTRUCT_VLAN_RSRC = "vlan-rsrc"
39+
CLI_CONSTRUCT_VXLAN_RSRC = "vxlan-rsrc"
40+
CLI_CONSTRUCT_SUBNET_RSRC = "subnet-rsrc"
41+
CLI_OPER_GET = "get"
42+
CLI_OPER_CREATE = "create"
43+
CLI_OPER_DELETE = "delete"
44+
CLI_OPER_ATTACH = "attach"
45+
CLI_OPER_DETACH = "detach"
4246
)
4347

48+
var constructs = []string{
49+
CLI_CONSTRUCT_GLOBAL,
50+
CLI_CONSTRUCT_NW,
51+
CLI_CONSTRUCT_EP,
52+
CLI_CONSTRUCT_VLAN_RSRC,
53+
CLI_CONSTRUCT_VXLAN_RSRC,
54+
CLI_CONSTRUCT_SUBNET_RSRC,
55+
}
56+
4457
var validOperList = []string{CLI_OPER_GET, CLI_OPER_CREATE, CLI_OPER_DELETE, CLI_OPER_ATTACH, CLI_OPER_DETACH}
4558

4659
type CliError struct {
@@ -87,16 +100,18 @@ type Construct struct {
87100
}
88101

89102
func (c *Construct) String() string {
90-
return fmt.Sprintf("%s or %s", CLI_CONSTRUCT_NW, CLI_CONSTRUCT_EP)
103+
return fmt.Sprintf("%s", constructs)
91104
}
92105

93106
func (c *Construct) Set(val string) error {
94-
if val != CLI_CONSTRUCT_NW && val != CLI_CONSTRUCT_EP && val != CLI_CONSTRUCT_GLOBAL {
95-
return &CliError{Desc: fmt.Sprintf("invalid value for construct (%s). Allowed values: %s",
96-
val, c.String())}
107+
for _, str := range constructs {
108+
if str == val {
109+
c.val = val
110+
return nil
111+
}
97112
}
98-
c.val = val
99-
return nil
113+
return &CliError{Desc: fmt.Sprintf("invalid value for construct (%s). Allowed values: %s",
114+
val, c.String())}
100115
}
101116

102117
func (c *Construct) Get() interface{} {
@@ -444,6 +459,30 @@ func executeOpts(opts *cliOpts) error {
444459
log.Fatalf("error '%s' \n", err)
445460
}
446461
return err
462+
case CLI_CONSTRUCT_VLAN_RSRC:
463+
fallthrough
464+
case CLI_CONSTRUCT_VXLAN_RSRC:
465+
fallthrough
466+
case CLI_CONSTRUCT_SUBNET_RSRC:
467+
if opts.oper.Get() == CLI_OPER_GET {
468+
if CLI_CONSTRUCT_VLAN_RSRC == opts.construct.Get() {
469+
rsrc := &resources.AutoVlanCfgResource{}
470+
rsrc.StateDriver = etcdDriver
471+
state = rsrc
472+
}
473+
if CLI_CONSTRUCT_VXLAN_RSRC == opts.construct.Get() {
474+
rsrc := &resources.AutoVxlanCfgResource{}
475+
rsrc.StateDriver = etcdDriver
476+
state = rsrc
477+
}
478+
if CLI_CONSTRUCT_SUBNET_RSRC == opts.construct.Get() {
479+
rsrc := &resources.AutoSubnetCfgResource{}
480+
rsrc.StateDriver = etcdDriver
481+
state = rsrc
482+
}
483+
} else {
484+
return fmt.Errorf("Only get operation is supported for resources")
485+
}
447486
}
448487

449488
switch opts.oper.Get() {

0 commit comments

Comments
 (0)