Skip to content

Commit 35377a7

Browse files
author
Vipin Jain
committed
centralize resource allocation
1 parent 743329e commit 35377a7

File tree

10 files changed

+1192
-446
lines changed

10 files changed

+1192
-446
lines changed

drivers/ovsdriver.go

+8-212
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import (
2424

2525
"github.com/contiv/libovsdb"
2626
"github.com/contiv/netplugin/core"
27-
"github.com/contiv/netplugin/gstate"
28-
"github.com/contiv/netplugin/netutils"
2927
)
3028

3129
// implements the NetworkDriver and EndpointDriver interface for an vlan based
@@ -238,7 +236,7 @@ func (d *OvsDriver) createDeletePort(portName, intfName, intfType, id string,
238236
}
239237

240238
if intfOptions != nil {
241-
log.Printf("using options %v \n", intfOptions)
239+
// log.Printf("using options %v \n", intfOptions)
242240
intf["options"], err = libovsdb.NewOvsMap(intfOptions)
243241
if err != nil {
244242
log.Printf("error '%s' creating options from %v \n", err, intfOptions)
@@ -426,169 +424,35 @@ func (d *OvsDriver) Deinit() {
426424
}
427425

428426
func (d *OvsDriver) CreateNetwork(id string) error {
429-
var err error
430-
var extPktTag, pktTag uint
431-
var subnetLen uint
432-
var subnetIp string
433-
var gOper gstate.Oper
434-
435-
operNwState := OvsOperNetworkState{StateDriver: d.stateDriver}
436-
err = operNwState.Read(id)
437-
if err == nil {
438-
return err
439-
}
440-
441427
cfgNetState := OvsCfgNetworkState{StateDriver: d.stateDriver}
442-
err = cfgNetState.Read(id)
443-
if err != nil {
444-
return err
445-
}
446-
447-
err = gOper.Read(d.stateDriver, cfgNetState.Tenant)
448-
if err != nil {
449-
return err
450-
}
451-
452-
operNwState = OvsOperNetworkState{StateDriver: d.stateDriver,
453-
Id: cfgNetState.Id, Tenant: cfgNetState.Tenant,
454-
PktTagType: cfgNetState.PktTagType,
455-
DefaultGw: cfgNetState.DefaultGw}
456-
457-
if cfgNetState.PktTag == "auto" {
458-
operNwState.PktTagType = gOper.DefaultNetType
459-
if gOper.DefaultNetType == "vlan" {
460-
pktTag, err = gOper.AllocVlan()
461-
if err != nil {
462-
return err
463-
}
464-
} else if gOper.DefaultNetType == "vxlan" {
465-
extPktTag, pktTag, err = gOper.AllocVxlan()
466-
if err != nil {
467-
return err
468-
}
469-
}
470-
471-
err = gOper.Update(d.stateDriver)
472-
if err != nil {
473-
return err
474-
}
475-
476-
log.Printf("allocated vlan %d vxlan %d \n", pktTag, extPktTag)
477-
operNwState.ExtPktTag = int(extPktTag)
478-
operNwState.PktTag = int(pktTag)
479-
} else {
480-
if cfgNetState.PktTagType == "vxlan" {
481-
pktTag, err = gOper.AllocLocalVlan()
482-
if err != nil {
483-
return err
484-
}
485-
486-
err = gOper.Update(d.stateDriver)
487-
if err != nil {
488-
log.Printf("error updating the global state - %s \n", err)
489-
return err
490-
}
491-
492-
operNwState.PktTag = int(pktTag)
493-
operNwState.ExtPktTag, err = strconv.Atoi(cfgNetState.PktTag)
494-
} else if cfgNetState.PktTagType == "vlan" {
495-
operNwState.PktTag, err = strconv.Atoi(cfgNetState.PktTag)
496-
if err != nil {
497-
return err
498-
}
499-
}
500-
}
501-
502-
if cfgNetState.SubnetIp == "auto" {
503-
subnetLen = gOper.AllocSubnetLen
504-
subnetIp, err = gOper.AllocSubnet()
505-
if err != nil {
506-
return err
507-
}
508-
509-
err = gOper.Update(d.stateDriver)
510-
if err != nil {
511-
return err
512-
}
513-
log.Printf("allocated subnet %s/%d \n", subnetIp, subnetLen)
514-
} else {
515-
subnetLen = cfgNetState.SubnetLen
516-
subnetIp = cfgNetState.SubnetIp
517-
}
518-
operNwState.SubnetIp = subnetIp
519-
operNwState.SubnetLen = subnetLen
520-
521-
netutils.InitSubnetBitset(&operNwState.IpAllocMap, subnetLen)
522-
err = operNwState.Write()
428+
err := cfgNetState.Read(id)
523429
if err != nil {
430+
log.Printf("Failed to read net %s \n", cfgNetState.Id)
524431
return err
525432
}
433+
log.Printf("create net %s \n", cfgNetState.Id)
526434

527435
return nil
528436
}
529437

530438
func (d *OvsDriver) DeleteNetwork(value string) error {
439+
440+
// no driver operation for network delete
531441
var err error
532-
var gOper gstate.Oper
533442

534443
cfgNetState := OvsCfgNetworkState{}
535444
err = cfgNetState.Unmarshal(value)
536445
if err != nil {
537446
log.Printf("Failed to unmarshal network config, err '%s' \n", err)
538447
return err
539448
}
540-
541-
operNwState := OvsOperNetworkState{StateDriver: d.stateDriver}
542-
err = operNwState.Read(cfgNetState.Id)
543-
if err != nil {
544-
return core.ErrIfKeyExists(err)
545-
}
546-
547-
err = gOper.Read(d.stateDriver, operNwState.Tenant)
548-
if err != nil {
549-
return err
550-
}
551-
552-
if operNwState.PktTagType == "vlan" {
553-
err = gOper.FreeVlan(uint(operNwState.PktTag))
554-
if err != nil {
555-
return err
556-
}
557-
} else if operNwState.PktTagType == "vxlan" {
558-
err = gOper.FreeVxlan(uint(operNwState.ExtPktTag),
559-
uint(operNwState.PktTag))
560-
if err != nil {
561-
return err
562-
}
563-
}
564-
565-
if cfgNetState.SubnetIp == "auto" {
566-
log.Printf("freeing subnet %s/%d \n",
567-
operNwState.SubnetIp, operNwState.SubnetLen)
568-
err = gOper.FreeSubnet(operNwState.SubnetIp)
569-
if err != nil {
570-
log.Printf("error '%s' freeing the subnet \n", err)
571-
}
572-
}
573-
574-
err = gOper.Update(d.stateDriver)
575-
if err != nil {
576-
log.Printf("error updating the global state - %s \n", err)
577-
return err
578-
}
579-
580-
err = operNwState.Clear()
581-
if err != nil {
582-
return core.ErrIfKeyExists(err)
583-
}
449+
log.Printf("delete net %s \n", cfgNetState.Id)
584450

585451
return nil
586452
}
587453

588454
func (d *OvsDriver) CreateEndpoint(id string) error {
589455
var err error
590-
var ipAddrBit uint = 0
591-
var found bool
592456

593457
// add an internal ovs port with vlan-tag information from the state
594458
portName := d.getPortName()
@@ -621,14 +485,6 @@ func (d *OvsDriver) CreateEndpoint(id string) error {
621485
intfType = ""
622486
}
623487

624-
cfgNetState := OvsCfgNetworkState{StateDriver: d.stateDriver}
625-
err = cfgNetState.Read(epCfg.NetId)
626-
if err != nil {
627-
return err
628-
}
629-
630-
// TODO: use etcd distributed lock to ensure atomicity of this operation
631-
// this is valid for EpCount, defer the unlocking for intermediate returns
632488
operNwState := OvsOperNetworkState{StateDriver: d.stateDriver}
633489
err = operNwState.Read(epCfg.NetId)
634490
if err != nil {
@@ -647,52 +503,13 @@ func (d *OvsDriver) CreateEndpoint(id string) error {
647503
}
648504
}()
649505

650-
ipAddress := epCfg.IpAddress
651-
if ipAddress == "auto" {
652-
if ipAddrBit, found = operNwState.IpAllocMap.NextClear(0); !found {
653-
log.Printf("auto allocation failed - address exhaustion in subnet %s/%d \n",
654-
operNwState.SubnetIp, operNwState.SubnetLen)
655-
return err
656-
}
657-
ipAddress, err = netutils.GetSubnetIp(
658-
operNwState.SubnetIp, operNwState.SubnetLen, 32, ipAddrBit)
659-
if err != nil {
660-
log.Printf("error acquiring subnet ip '%s' \n", err)
661-
return err
662-
}
663-
log.Printf("Ep %s was allocated ip address %s \n", id, ipAddress)
664-
} else if ipAddress != "" && operNwState.SubnetIp != "" {
665-
ipAddrBit, err = netutils.GetIpNumber(
666-
operNwState.SubnetIp, operNwState.SubnetLen, 32, ipAddress)
667-
if err != nil {
668-
log.Printf("error getting host id from hostIp %s Subnet %s/%d err '%s'\n",
669-
ipAddress, operNwState.SubnetIp, operNwState.SubnetLen, err)
670-
return err
671-
}
672-
}
673-
operNwState.IpAllocMap.Set(ipAddrBit)
674-
675-
// deprecate - bitset.WordCount gives the following value
676-
operNwState.EpCount += 1
677-
err = operNwState.Write()
678-
if err != nil {
679-
return err
680-
}
681-
defer func() {
682-
if err != nil {
683-
//XXX: need to return allocated ip back to the pool in case of failure
684-
operNwState.EpCount -= 1
685-
operNwState.Write()
686-
}
687-
}()
688-
689506
operEpState := OvsOperEndpointState{
690507
StateDriver: d.stateDriver,
691508
Id: id,
692509
PortName: portName,
693510
NetId: epCfg.NetId,
694511
ContName: epCfg.ContName,
695-
IpAddress: ipAddress,
512+
IpAddress: epCfg.IpAddress,
696513
IntfName: intfName,
697514
HomingHost: epCfg.HomingHost,
698515
VtepIp: epCfg.VtepIp}
@@ -752,27 +569,6 @@ func (d *OvsDriver) DeleteEndpoint(value string) (err error) {
752569
return err
753570
}
754571

755-
operNwState := OvsOperNetworkState{StateDriver: d.stateDriver}
756-
err = operNwState.Read(epOper.NetId)
757-
if err != nil {
758-
return err
759-
}
760-
761-
ipAddrBit, err := netutils.GetIpNumber(
762-
operNwState.SubnetIp, operNwState.SubnetLen, 32, epOper.IpAddress)
763-
if err != nil {
764-
log.Printf("error getting host id from %s subnet %s/%d err '%s'\n",
765-
epOper.IpAddress, operNwState.SubnetIp, operNwState.SubnetLen, err)
766-
} else {
767-
operNwState.IpAllocMap.Clear(ipAddrBit)
768-
}
769-
770-
operNwState.EpCount -= 1
771-
err = operNwState.Write()
772-
if err != nil {
773-
return err
774-
}
775-
776572
return nil
777573
}
778574

gstate/gstate.go

+22-5
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,12 @@ func (g *Oper) AllocVxlan() (vxlan uint, localVlan uint, err error) {
262262

263263
func (g *Oper) FreeVxlan(vxlan uint, localVlan uint) error {
264264
if !g.FreeLocalVlans.Test(localVlan) {
265-
g.FreeLocalVlans.Clear(localVlan)
265+
g.FreeLocalVlans.Set(localVlan)
266266
}
267267

268268
vxlan = vxlan - g.FreeVxlansStart
269269
if !g.FreeVxlans.Test(vxlan) {
270-
g.FreeVxlans.Clear(vxlan)
270+
g.FreeVxlans.Set(vxlan)
271271
}
272272

273273
return nil
@@ -279,15 +279,15 @@ func (g *Oper) AllocLocalVlan() (uint, error) {
279279
return 0, errors.New("no vlans available ")
280280
}
281281

282-
g.FreeLocalVlans.Set(vlan)
282+
g.FreeLocalVlans.Clear(vlan)
283283

284284
return vlan, nil
285285
}
286286

287287
// be idempotent, don't complain if vlan is already freed
288288
func (g *Oper) FreeLocalVlan(vlan uint) error {
289289
if !g.FreeLocalVlans.Test(vlan) {
290-
g.FreeLocalVlans.Clear(vlan)
290+
g.FreeLocalVlans.Set(vlan)
291291
}
292292
return nil
293293
}
@@ -333,11 +333,28 @@ func (g *Oper) AllocVlan() (uint, error) {
333333
// be idempotent, don't complain if vlan is already freed
334334
func (g *Oper) FreeVlan(vlan uint) error {
335335
if !g.FreeVlans.Test(vlan) {
336-
g.FreeVlans.Clear(vlan)
336+
g.FreeVlans.Set(vlan)
337337
}
338338
return nil
339339
}
340340

341+
func (g *Oper) CheckVlanInUse(vlan uint) error {
342+
if !g.FreeVlans.Test(vlan) {
343+
return errors.New("specified vlan not available")
344+
}
345+
346+
return nil
347+
}
348+
349+
func (g *Oper) SetVlan(vlan uint) (err error) {
350+
err = g.CheckVlanInUse(vlan)
351+
if err == nil {
352+
g.FreeVlans.Clear(vlan)
353+
}
354+
355+
return
356+
}
357+
341358
func (g *Oper) AllocSubnet() (string, error) {
342359

343360
subnetId, found := g.FreeSubnets.NextSet(0)

gstate/gstate_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,21 @@ func TestGlobalConfigSpecificVlans(t *testing.T) {
9999
t.Fatalf("error - expecting vlan %d but allocated %d \n", 200, vlan)
100100
}
101101

102+
err = g.CheckVlanInUse(vlan)
103+
if err == nil {
104+
t.Fatalf("error - vlan %d should have returned in use \n", vlan)
105+
}
106+
107+
err = g.SetVlan(vlan + 1)
108+
if err != nil {
109+
t.Fatalf("error - vlan %d should be allowed for allocation \n", vlan+1)
110+
}
111+
112+
err = g.FreeVlan(vlan + 1)
113+
if err != nil {
114+
t.Fatalf("error freeing allocated vlan %d - err '%s' \n", vlan, err)
115+
}
116+
102117
err = g.FreeVlan(vlan)
103118
if err != nil {
104119
t.Fatalf("error freeing allocated vlan %d - err '%s' \n", vlan, err)
@@ -257,6 +272,21 @@ func TestGlobalConfigDefaultVxlanWithVlans(t *testing.T) {
257272
t.Fatalf("error - invalid vlan allocated %d \n", localVlan)
258273
}
259274

275+
err = g.CheckVlanInUse(vlan)
276+
if err == nil {
277+
t.Fatalf("error - vlan %d should have returned in use \n", vlan)
278+
}
279+
280+
err = g.SetVlan(vlan + 1)
281+
if err != nil {
282+
t.Fatalf("error - vlan %d should be allowed for allocation \n", vlan+1)
283+
}
284+
285+
err = g.FreeVlan(vlan + 1)
286+
if err != nil {
287+
t.Fatalf("error freeing allocated vlan %d - err '%s' \n", vlan, err)
288+
}
289+
260290
err = g.FreeVlan(vlan)
261291
if err != nil {
262292
t.Fatalf("error freeing allocated vlan %d - err '%s' \n", vlan, err)

0 commit comments

Comments
 (0)