@@ -272,6 +272,8 @@ class BGPPeerMgr(Manager):
272272 [
273273 ("meta" , "localhost/bgp_asn" ),
274274 ("neigmeta" , "" ),
275+ ("local_addresses" , "" ),
276+ ("interfaces" , "" ),
275277 ],
276278 "CONFIG_DB" ,
277279 swsscommon .CFG_BGP_NEIGHBOR_TABLE_NAME
@@ -290,8 +292,42 @@ class BGPPeerMgr(Manager):
290292 vrf , nbr = key .split ('|' , 1 )
291293 if key not in self .peers :
292294 cmd = None
295+
296+ if "local_addr" not in data :
297+ syslog .syslog (syslog .LOG_WARNING , 'Peer {}. Error in missing required attribute "local_addr"' .format (key ))
298+ else :
299+ # The bgp session that belongs to a vnet cannot be advertised as the default BGP session.
300+ # So we need to check whether this bgp session belongs to a vnet.
301+ interface = InterfaceMgr .get_local_interface (self .directory , data ["local_addr" ])
302+ if not interface :
303+ syslog .syslog (syslog .LOG_INFO ,
304+ 'Peer {} with local address {} wait for the corresponding interface to be set' .format (
305+ key ,
306+ data ["local_addr" ]
307+ )
308+ )
309+ return False
310+ vnet = InterfaceMgr .get_vnet (interface )
311+ if vnet :
312+ # Ignore the bgp session that is in a vnet
313+ syslog .syslog (
314+ syslog .LOG_INFO ,
315+ 'Ignore the BGP peer {} as the interface {} is in vnet {}' .format (
316+ key ,
317+ interface ,
318+ vnet
319+ )
320+ )
321+ return True
322+
293323 neigmeta = self .directory .get_slot ("neigmeta" )
294324 if 'name' in data and data ["name" ] not in neigmeta :
325+ syslog .syslog (syslog .LOG_INFO ,
326+ 'Peer {} with neighbor name {} wait for the corresponding neighbor metadata to be set' .format (
327+ key ,
328+ data ["name" ]
329+ )
330+ )
295331 return False
296332 try :
297333 cmd = self .templates ["add" ].render (
@@ -390,6 +426,121 @@ class BGPPeerMgr(Manager):
390426 return peers
391427
392428
429+ class InterfaceMgr (Manager ):
430+ def __init__ (self , daemon , directory , interface_table = swsscommon .CFG_INTF_TABLE_NAME ):
431+ super (InterfaceMgr , self ).__init__ (
432+ daemon ,
433+ directory ,
434+ [],
435+ "CONFIG_DB" ,
436+ interface_table
437+ )
438+
439+ def set_handler (self , key , data ):
440+ # Interface table can have two keys,
441+ # one with ip prefix and one without ip prefix
442+ if '|' in key :
443+ data = {}
444+ data ["interface" ], network = key .split ('|' , 1 )
445+ try :
446+ network = netaddr .IPNetwork (str (network ))
447+ except :
448+ syslog .syslog (
449+ syslog .LOG_WARNING ,
450+ 'Subnet {} format is wrong for interface {}' .format (
451+ network ,
452+ data ["interface" ]
453+ )
454+ )
455+ return False
456+ data ["prefixlen" ] = str (network .prefixlen )
457+ ip = str (network .ip )
458+ self .directory .put ("local_addresses" , ip , data )
459+ else :
460+ self .directory .put ("interfaces" , key , data )
461+ return True
462+
463+ def del_handler (self , key ):
464+ if '|' in key :
465+ interface , network = key .split ('|' , 1 )
466+ try :
467+ network = netaddr .IPNetwork (str (network ))
468+ except :
469+ syslog .syslog (
470+ syslog .LOG_WARNING ,
471+ 'Subnet {} format is wrong for interface {}' .format (
472+ network ,
473+ interface
474+ )
475+ )
476+ return False
477+ ip = str (network .ip )
478+ self .directory .remove ("local_addresses" , ip )
479+ else :
480+ self .directory .remove ("interfaces" , key )
481+
482+ @staticmethod
483+ def get_local_interface (directory , local_addr ):
484+ """
485+ @summary: Get interface according to the local address from the directory
486+ @param directory: Directory object that stored metadata of interfaces
487+ @param local_addr: Local address of the interface
488+ @return: Return the metadata of the interface with the local address
489+ If the interface has not been set, return None
490+ """
491+ local_addresses = directory .get_slot ("local_addresses" )
492+ # Check if the local address of this bgp session has been set
493+ if local_addr not in local_addresses :
494+ return None
495+ local_address = local_addresses [local_addr ]
496+ interfaces = directory .get_slot ("interfaces" )
497+ # Check if the information for the interface of this local address has been set
498+ if local_address .has_key ("interface" ) and local_address ["interface" ] in interfaces :
499+ return interfaces [local_address ["interface" ]]
500+ else :
501+ return None
502+
503+ @staticmethod
504+ def get_vnet (interface ):
505+ """
506+ @summary: Get the VNet name of the interface
507+ @param interface: The metadata of the interface
508+ @return: Return the vnet name of the interface if this interface belongs to a vnet,
509+ Otherwise return None
510+ """
511+ if interface .has_key ("vnet_name" ) and interface ["vnet_name" ]:
512+ return interface ["vnet_name" ]
513+ else :
514+ return None
515+
516+
517+ class LoopbackInterfaceMgr (InterfaceMgr ):
518+ def __init__ (self , daemon , directory ):
519+ super (LoopbackInterfaceMgr , self ).__init__ (
520+ daemon ,
521+ directory ,
522+ swsscommon .CFG_LOOPBACK_INTERFACE_TABLE_NAME
523+ )
524+
525+
526+ class VlanInterfaceMgr (InterfaceMgr ):
527+ def __init__ (self , daemon , directory ):
528+ super (VlanInterfaceMgr , self ).__init__ (
529+ daemon ,
530+ directory ,
531+ swsscommon .CFG_VLAN_INTF_TABLE_NAME
532+ )
533+
534+
535+ class PortChannelInterfaceMgr (InterfaceMgr ):
536+ def __init__ (self , daemon , directory ):
537+ super (PortChannelInterfaceMgr , self ).__init__ (
538+ daemon ,
539+ directory ,
540+ swsscommon .CFG_LAG_INTF_TABLE_NAME
541+ )
542+
543+
393544def wait_for_bgpd ():
394545 # wait for 20 seconds
395546 stop_time = datetime .datetime .now () + datetime .timedelta (seconds = 20 )
@@ -408,6 +559,10 @@ def main():
408559 BGPDeviceMetaMgr ,
409560 BGPNeighborMetaMgr ,
410561 BGPPeerMgr ,
562+ InterfaceMgr ,
563+ LoopbackInterfaceMgr ,
564+ VlanInterfaceMgr ,
565+ PortChannelInterfaceMgr ,
411566 ]
412567 wait_for_bgpd ()
413568 daemon = Daemon ()
0 commit comments