28
28
STACK_STATE_NONE = - 1
29
29
30
30
# LACP not configured
31
- LACP_STATE_NONE = - 1
32
-
33
- # Initial state, no packets received yet
31
+ LACP_ACTOR_NOTCONFIGURED = - 1
32
+ # Not receiving packets from the actor & port is down
33
+ LACP_ACTOR_NONE = 0
34
+ # Not receiving packets from the actor & port is up
34
35
LACP_ACTOR_INIT = 1
35
- # LACP connection is up and receiving packets
36
+ # Receiving LACP packets with sync bit set
36
37
LACP_ACTOR_UP = 3
37
- # LACP is down
38
- LACP_ACTOR_NOACT = 5
38
+ # LACP actor is not sending LACP with sync bit set
39
+ LACP_ACTOR_NOSYNC = 5
39
40
LACP_ACTOR_DISPLAY_DICT = {
40
- LACP_STATE_NONE : 'NONE' ,
41
+ LACP_ACTOR_NOTCONFIGURED : 'NOT_CONFIGURED' ,
42
+ LACP_ACTOR_NONE : 'NONE' ,
41
43
LACP_ACTOR_INIT : 'INITIALIZING' ,
42
44
LACP_ACTOR_UP : 'UP' ,
43
- LACP_ACTOR_NOACT : 'NO_ACTOR '
45
+ LACP_ACTOR_NOSYNC : 'NO_SYNC '
44
46
}
45
47
48
+ # LACP is not configured
49
+ LACP_PORT_NOTCONFIGURED = - 1
46
50
# Port is not a LACP port on the nominated DP
47
51
LACP_PORT_UNSELECTED = 1
48
52
# Port is a LACP port on the nominated DP, will send/receive
49
53
LACP_PORT_SELECTED = 2
50
- # Other cases: receive-only, etc.
54
+ # Port is a LACP port that is in standby
51
55
LACP_PORT_STANDBY = 3
52
56
LACP_PORT_DISPLAY_DICT = {
53
- LACP_STATE_NONE : 'NONE ' ,
57
+ LACP_PORT_NOTCONFIGURED : 'NOT_CONFIGURED ' ,
54
58
LACP_PORT_UNSELECTED : 'UNSELECTED' ,
55
59
LACP_PORT_SELECTED : 'SELECTED' ,
56
60
LACP_PORT_STANDBY : 'STANDBY'
@@ -91,6 +95,12 @@ class Port(Conf):
91
95
# experimental active LACP
92
96
'lacp_collect_and_distribute' : False ,
93
97
# if true, forces LACP port to collect and distribute when syncing with the peer.
98
+ 'lacp_unselected' : False ,
99
+ # if true, forces LACP port to be in unselected state
100
+ 'lacp_selected' : False ,
101
+ # if true, forces LACP port to be in the selected state
102
+ 'lacp_standby' : False ,
103
+ # if true, forces LACP port to be in the standby state
94
104
'lacp_passthrough' : None ,
95
105
# If set, fail the lacp on this port if any of the peer ports are down.
96
106
'lacp_resp_interval' : 1 ,
@@ -146,6 +156,9 @@ class Port(Conf):
146
156
'lacp' : int ,
147
157
'lacp_active' : bool ,
148
158
'lacp_collect_and_distribute' : bool ,
159
+ 'lacp_unselected' : bool ,
160
+ 'lacp_selected' : bool ,
161
+ 'lacp_standby' : bool ,
149
162
'lacp_passthrough' : list ,
150
163
'lacp_resp_interval' : int ,
151
164
'loop_protect' : bool ,
@@ -203,6 +216,9 @@ def __init__(self, _id, dp_id, conf=None):
203
216
self .lacp = None
204
217
self .lacp_active = None
205
218
self .lacp_collect_and_distribute = None
219
+ self .lacp_unselected = None
220
+ self .lacp_selected = None
221
+ self .lacp_standby = None
206
222
self .lacp_passthrough = None
207
223
self .lacp_resp_interval = None
208
224
self .loop_protect = None
@@ -237,8 +253,8 @@ def __init__(self, _id, dp_id, conf=None):
237
253
self .dyn_phys_up = False
238
254
self .dyn_update_time = None
239
255
self .dyn_stack_current_state = STACK_STATE_NONE
240
- self .dyn_lacp_port_selected = LACP_STATE_NONE
241
- self .dyn_lacp_actor_state = LACP_STATE_NONE
256
+ self .dyn_lacp_port_selected = LACP_PORT_NOTCONFIGURED
257
+ self .dyn_lacp_actor_state = LACP_ACTOR_NOTCONFIGURED
242
258
self .dyn_stack_probe_info = {}
243
259
244
260
self .tagged_vlans = []
@@ -299,9 +315,9 @@ def check_config(self):
299
315
if key .startswith ('acl' ) and self .stack :
300
316
continue
301
317
val = getattr (self , key )
302
- if val != default_val and val :
303
- raise InvalidConfigError (
304
- 'Cannot have VLAN option %s: %s on non-VLAN port %s' % (key , val , self ))
318
+ test_config_condition (
319
+ val != default_val and val ,
320
+ 'Cannot have VLAN option %s: %s on non-VLAN port %s' % (key , val , self ))
305
321
test_config_condition (
306
322
self .hairpin and self .hairpin_unicast ,
307
323
'Cannot have both hairpin and hairpin_unicast enabled' )
@@ -369,15 +385,20 @@ def check_config(self):
369
385
'%6.6x' % org_tlv ['oui' ]) # pytype: disable=missing-parameter
370
386
org_tlvs .append (org_tlv )
371
387
self .lldp_beacon ['org_tlvs' ] = org_tlvs
372
- if self .acl_in and self .acls_in :
373
- raise InvalidConfigError ('found both acl_in and acls_in, use only acls_in' )
388
+ test_config_condition (
389
+ self .acl_in and self .acls_in ,
390
+ 'Found both acl_in and acls_in, use only acls_in' )
374
391
if self .acl_in and not isinstance (self .acl_in , list ):
375
392
self .acls_in = [self .acl_in ,]
376
393
self .acl_in = None
377
394
if self .acls_in :
378
395
for acl in self .acls_in :
379
396
test_config_condition (not isinstance (acl , (int , str )),
380
397
'ACL names must be int or str' )
398
+ lacp_options = [self .lacp_selected , self .lacp_unselected , self .lacp_standby ]
399
+ test_config_condition (
400
+ lacp_options .count (True ) > 1 ,
401
+ 'Cannot force multiple LACP port selection states' )
381
402
382
403
def finalize (self ):
383
404
if self .native_vlan :
@@ -439,20 +460,24 @@ def non_stack_forwarding(self):
439
460
return True
440
461
441
462
# LACP functions
442
- def lacp_update (self , lacp_up , now = None , lacp_pkt = None ):
463
+ def lacp_actor_update (self , lacp_up , now = None , lacp_pkt = None , cold_start = False ):
443
464
"""
444
- Update the LACP state
465
+ Update the LACP actor state
445
466
Args:
446
467
lacp_up (bool): The intended LACP/port state
447
- now: Current time
448
- lacp_pkt: Received LACP packet
468
+ now (float): Current time
469
+ lacp_pkt (PacketMeta): Received LACP packet
470
+ cold_start (bool): Whether the port is being cold started
449
471
Returns:
450
- dyn_lacp_actor_state, dyn_lacp_current_state
472
+ current LACP actor state
451
473
"""
452
474
self .dyn_lacp_up = 1 if lacp_up else 0
453
475
self .dyn_lacp_updated_time = now
454
476
self .dyn_last_lacp_pkt = lacp_pkt
455
- if not self .dyn_phys_up :
477
+ if cold_start :
478
+ # Cold starting, so revert to unconfigured LACP state
479
+ self .actor_notconfigured ()
480
+ elif not self .running ():
456
481
# Phys not up so we do not initialize actor states
457
482
self .actor_none ()
458
483
elif not lacp_pkt :
@@ -464,10 +489,40 @@ def lacp_update(self, lacp_up, now=None, lacp_pkt=None):
464
489
# Receiving packets & LACP is UP
465
490
self .actor_up ()
466
491
else :
467
- # Receiving packets but LACP is DOWN
468
- self .actor_noact ()
492
+ # Receiving packets but LACP sync bit is not set
493
+ self .actor_nosync ()
469
494
return self .actor_state ()
470
495
496
+ def lacp_port_update (self , selected , cold_start = False ):
497
+ """
498
+ Updates the LACP port selection state
499
+ Args:
500
+ selected (bool): Whether the port's DPID is the selected one
501
+ cold_start (bool): Whether the port is being cold started
502
+ Returns
503
+ current lacp port state
504
+ """
505
+ if cold_start :
506
+ # Cold starting, so revert to unconfigured state
507
+ self .deconfigure_port ()
508
+ elif self .lacp_selected :
509
+ # Can configure LACP port to be forced SELECTED
510
+ self .select_port ()
511
+ elif self .lacp_standby :
512
+ # Can configure LACP port to be forced STANDBY
513
+ self .standby_port ()
514
+ elif self .lacp_unselected :
515
+ # Can configure LACP port to be force UNSELECTED
516
+ self .deselect_port ()
517
+ else :
518
+ if selected :
519
+ # Belongs on chosen DP for LAG, so SELECT port
520
+ self .select_port ()
521
+ else :
522
+ # Doesn't belong on chosen DP for LAG, DESELECT port
523
+ self .deselect_port ()
524
+ return self .lacp_port_state ()
525
+
471
526
def get_lacp_flags (self ):
472
527
"""
473
528
Get the LACP flags for the state the port is in
@@ -486,25 +541,29 @@ def is_actor_up(self):
486
541
"""Return true if the LACP actor state is UP"""
487
542
return self .dyn_lacp_actor_state == LACP_ACTOR_UP
488
543
489
- def is_actor_noact (self ):
490
- """Return true if the LACP actor state is NOACT """
491
- return self .dyn_lacp_actor_state == LACP_ACTOR_NOACT
544
+ def is_actor_nosync (self ):
545
+ """Return true if the LACP actor state is NOSYNC """
546
+ return self .dyn_lacp_actor_state == LACP_ACTOR_NOSYNC
492
547
493
548
def is_actor_init (self ):
494
549
"""Return true if the LACP actor state is INIT"""
495
550
return self .dyn_lacp_actor_state == LACP_ACTOR_INIT
496
551
497
552
def is_actor_none (self ):
498
553
"""Return true if the LACP actor state is NONE"""
499
- return self .dyn_lacp_actor_state == LACP_STATE_NONE
554
+ return self .dyn_lacp_actor_state == LACP_ACTOR_NONE
500
555
501
556
def actor_state (self ):
502
557
"""Return the current LACP actor state"""
503
558
return self .dyn_lacp_actor_state
504
559
560
+ def actor_notconfigured (self ):
561
+ """Set the LACP actor state to NOTCONFIGURED"""
562
+ self .dyn_lacp_actor_state = LACP_ACTOR_NOTCONFIGURED
563
+
505
564
def actor_none (self ):
506
565
"""Set the LACP actor state to NONE"""
507
- self .dyn_lacp_actor_state = LACP_STATE_NONE
566
+ self .dyn_lacp_actor_state = LACP_ACTOR_NONE
508
567
509
568
def actor_init (self ):
510
569
"""Set the LACP actor state to INIT"""
@@ -514,9 +573,9 @@ def actor_up(self):
514
573
"""Set the LACP actor state to UP"""
515
574
self .dyn_lacp_actor_state = LACP_ACTOR_UP
516
575
517
- def actor_noact (self ):
518
- """Set the LACP actor state to NOACT """
519
- self .dyn_lacp_actor_state = LACP_ACTOR_NOACT
576
+ def actor_nosync (self ):
577
+ """Set the LACP actor state to NOSYNC """
578
+ self .dyn_lacp_actor_state = LACP_ACTOR_NOSYNC
520
579
521
580
def actor_state_name (self , state ):
522
581
"""Return the string of the actor state"""
@@ -532,7 +591,7 @@ def is_port_unselected(self):
532
591
return self .dyn_lacp_port_selected == LACP_PORT_UNSELECTED
533
592
534
593
def is_port_standby (self ):
535
- """Return true if the lacp is a STANDBY port"""
594
+ """Return true if the lacp is a port in STANDBY """
536
595
return self .dyn_lacp_port_selected == LACP_PORT_STANDBY
537
596
538
597
def lacp_port_state (self ):
@@ -548,9 +607,13 @@ def deselect_port(self):
548
607
self .dyn_lacp_port_selected = LACP_PORT_UNSELECTED
549
608
550
609
def standby_port (self ):
551
- """Set the LACP port to STANDBY"""
610
+ """Set LACP port state to STANDBY"""
552
611
self .dyn_lacp_port_selected = LACP_PORT_STANDBY
553
612
613
+ def deconfigure_port (self ):
614
+ """Set LACP port state to NOTCONFIGURED"""
615
+ self .dyn_lacp_port_selected = LACP_PORT_NOTCONFIGURED
616
+
554
617
def port_role_name (self , state ):
555
618
"""Return the LACP port role state name"""
556
619
return LACP_PORT_DISPLAY_DICT [state ]
0 commit comments