60
60
CFG_LOOPBACK_ID_MAX_VAL = 999
61
61
CFG_LOOPBACK_NO = "<0-999>"
62
62
63
+ CFG_PORTCHANNEL_PREFIX = "PortChannel"
64
+ CFG_PORTCHANNEL_PREFIX_LEN = 11
65
+ CFG_PORTCHANNEL_NAME_TOTAL_LEN_MAX = 15
66
+ CFG_PORTCHANNEL_MAX_VAL = 9999
67
+ CFG_PORTCHANNEL_NO = "<0-9999>"
68
+
69
+ PORT_MTU = "mtu"
70
+ PORT_SPEED = "speed"
63
71
64
72
asic_type = None
65
73
@@ -390,6 +398,45 @@ def is_interface_bind_to_vrf(config_db, interface_name):
390
398
return True
391
399
return False
392
400
401
+ def is_portchannel_name_valid (portchannel_name ):
402
+ """Port channel name validation
403
+ """
404
+
405
+ # Return True if Portchannel name is PortChannelXXXX (XXXX can be 0-9999)
406
+ if portchannel_name [:CFG_PORTCHANNEL_PREFIX_LEN ] != CFG_PORTCHANNEL_PREFIX :
407
+ return False
408
+ if (portchannel_name [CFG_PORTCHANNEL_PREFIX_LEN :].isdigit () is False or
409
+ int (portchannel_name [CFG_PORTCHANNEL_PREFIX_LEN :]) > CFG_PORTCHANNEL_MAX_VAL ) :
410
+ return False
411
+ if len (portchannel_name ) > CFG_PORTCHANNEL_NAME_TOTAL_LEN_MAX :
412
+ return False
413
+ return True
414
+
415
+ def is_portchannel_present_in_db (db , portchannel_name ):
416
+ """Check if Portchannel is present in Config DB
417
+ """
418
+
419
+ # Return True if Portchannel name exists in the CONFIG_DB
420
+ portchannel_list = db .get_table (CFG_PORTCHANNEL_PREFIX )
421
+ if portchannel_list is None :
422
+ return False
423
+ if portchannel_name in portchannel_list :
424
+ return True
425
+ return False
426
+
427
+ def is_port_member_of_this_portchannel (db , port_name , portchannel_name ):
428
+ """Check if a port is member of given portchannel
429
+ """
430
+ portchannel_list = db .get_table (CFG_PORTCHANNEL_PREFIX )
431
+ if portchannel_list is None :
432
+ return False
433
+
434
+ for k ,v in db .get_table ('PORTCHANNEL_MEMBER' ):
435
+ if (k == portchannel_name ) and (v == port_name ):
436
+ return True
437
+
438
+ return False
439
+
393
440
# Return the namespace where an interface belongs
394
441
# The port name input could be in default mode or in alias mode.
395
442
def get_port_namespace (port ):
@@ -1330,9 +1377,64 @@ def add_portchannel_member(ctx, portchannel_name, port_name):
1330
1377
ctx .fail ("{} is configured as mirror destination port" .format (port_name ))
1331
1378
1332
1379
# Check if the member interface given by user is valid in the namespace.
1333
- if interface_name_is_valid (db , port_name ) is False :
1380
+ if port_name . startswith ( "Ethernet" ) is False or interface_name_is_valid (db , port_name ) is False :
1334
1381
ctx .fail ("Interface name is invalid. Please enter a valid interface name!!" )
1335
1382
1383
+ # Dont proceed if the port channel name is not valid
1384
+ if is_portchannel_name_valid (portchannel_name ) is False :
1385
+ ctx .fail ("{} is invalid!, name should have prefix '{}' and suffix '{}'"
1386
+ .format (portchannel_name , CFG_PORTCHANNEL_PREFIX , CFG_PORTCHANNEL_NO ))
1387
+
1388
+ # Dont proceed if the port channel does not exist
1389
+ if is_portchannel_present_in_db (db , portchannel_name ) is False :
1390
+ ctx .fail ("{} is not present." .format (portchannel_name ))
1391
+
1392
+ # Dont allow a port to be member of port channel if it is configured with an IP address
1393
+ for key in db .get_table ('INTERFACE' ).keys ():
1394
+ if type (key ) != tuple :
1395
+ continue
1396
+ if key [0 ] == port_name :
1397
+ ctx .fail (" {} has ip address {} configured" .format (port_name , key [1 ]))
1398
+ return
1399
+
1400
+ # Dont allow a port to be member of port channel if it is configured as a VLAN member
1401
+ for k ,v in db .get_table ('VLAN_MEMBER' ):
1402
+ if v == port_name :
1403
+ ctx .fail ("%s Interface configured as VLAN_MEMBER under vlan : %s" % (port_name ,str (k )))
1404
+ return
1405
+
1406
+ # Dont allow a port to be member of port channel if it is already member of a port channel
1407
+ for k ,v in db .get_table ('PORTCHANNEL_MEMBER' ):
1408
+ if v == port_name :
1409
+ ctx .fail ("{} Interface is already member of {} " .format (v ,k ))
1410
+
1411
+ # Dont allow a port to be member of port channel if its speed does not match with existing members
1412
+ for k ,v in db .get_table ('PORTCHANNEL_MEMBER' ):
1413
+ if k == portchannel_name :
1414
+ member_port_entry = db .get_entry ('PORT' , v )
1415
+ port_entry = db .get_entry ('PORT' , port_name )
1416
+
1417
+ if member_port_entry is not None and port_entry is not None :
1418
+ member_port_speed = member_port_entry .get (PORT_SPEED )
1419
+
1420
+ port_speed = port_entry .get (PORT_SPEED )
1421
+ if member_port_speed != port_speed :
1422
+ ctx .fail ("Port speed of {} is different than the other members of the portchannel {}"
1423
+ .format (port_name , portchannel_name ))
1424
+
1425
+ # Dont allow a port to be member of port channel if its MTU does not match with portchannel
1426
+ portchannel_entry = db .get_entry ('PORTCHANNEL' , portchannel_name )
1427
+ if portchannel_entry and portchannel_entry .get (PORT_MTU ) is not None :
1428
+ port_entry = db .get_entry ('PORT' , port_name )
1429
+
1430
+ if port_entry and port_entry .get (PORT_MTU ) is not None :
1431
+ port_mtu = port_entry .get (PORT_MTU )
1432
+
1433
+ portchannel_mtu = portchannel_entry .get (PORT_MTU )
1434
+ if portchannel_mtu != port_mtu :
1435
+ ctx .fail ("Port MTU of {} is different than the {} MTU size"
1436
+ .format (port_name , portchannel_name ))
1437
+
1336
1438
db .set_entry ('PORTCHANNEL_MEMBER' , (portchannel_name , port_name ),
1337
1439
{'NULL' : 'NULL' })
1338
1440
@@ -1342,12 +1444,25 @@ def add_portchannel_member(ctx, portchannel_name, port_name):
1342
1444
@click .pass_context
1343
1445
def del_portchannel_member (ctx , portchannel_name , port_name ):
1344
1446
"""Remove member from portchannel"""
1447
+ # Dont proceed if the port channel name is not valid
1448
+ if is_portchannel_name_valid (portchannel_name ) is False :
1449
+ ctx .fail ("{} is invalid!, name should have prefix '{}' and suffix '{}'"
1450
+ .format (portchannel_name , CFG_PORTCHANNEL_PREFIX , CFG_PORTCHANNEL_NO ))
1451
+
1345
1452
db = ctx .obj ['db' ]
1346
1453
1347
1454
# Check if the member interface given by user is valid in the namespace.
1348
1455
if interface_name_is_valid (db , port_name ) is False :
1349
1456
ctx .fail ("Interface name is invalid. Please enter a valid interface name!!" )
1350
1457
1458
+ # Dont proceed if the port channel does not exist
1459
+ if is_portchannel_present_in_db (db , portchannel_name ) is False :
1460
+ ctx .fail ("{} is not present." .format (portchannel_name ))
1461
+
1462
+ # Dont proceed if the the port is not an existing member of the port channel
1463
+ if not is_port_member_of_this_portchannel (db , port_name , portchannel_name ):
1464
+ ctx .fail ("{} is not a member of portchannel {}" .format (port_name , portchannel_name ))
1465
+
1351
1466
db .set_entry ('PORTCHANNEL_MEMBER' , (portchannel_name , port_name ), None )
1352
1467
db .set_entry ('PORTCHANNEL_MEMBER' , portchannel_name + '|' + port_name , None )
1353
1468
@@ -2410,6 +2525,10 @@ def mtu(ctx, interface_name, interface_mtu, verbose):
2410
2525
if interface_name is None :
2411
2526
ctx .fail ("'interface_name' is None!" )
2412
2527
2528
+ portchannel_member_table = config_db .get_table ('PORTCHANNEL_MEMBER' )
2529
+ if interface_is_in_portchannel (portchannel_member_table , interface_name ):
2530
+ ctx .fail ("'interface_name' is in portchannel!" )
2531
+
2413
2532
if ctx .obj ['namespace' ] is DEFAULT_NAMESPACE :
2414
2533
command = "portconfig -p {} -m {}" .format (interface_name , interface_mtu )
2415
2534
else :
0 commit comments