1
1
from .manager import Manager
2
2
from .template import TemplateFabric
3
3
from swsscommon import swsscommon
4
+ from .managers_rm import ROUTE_MAPS
5
+ import ipaddress
6
+ from .log import log_info , log_err , log_debug
4
7
5
8
6
9
class AdvertiseRouteMgr (Manager ):
7
10
""" This class Advertises routes when ADVERTISE_NETWORK_TABLE in STATE_DB is updated """
11
+
8
12
def __init__ (self , common_objs , db , table ):
9
13
"""
10
14
Initialize the object
@@ -18,82 +22,105 @@ def __init__(self, common_objs, db, table):
18
22
db ,
19
23
table ,
20
24
)
21
-
25
+
22
26
self .directory .subscribe ([("CONFIG_DB" , swsscommon .CFG_DEVICE_METADATA_TABLE_NAME , "localhost/bgp_asn" ),], self .on_bgp_asn_change )
23
27
self .advertised_routes = dict ()
24
28
25
29
26
- OP_DELETE = 'DELETE'
27
- OP_ADD = 'ADD'
28
-
30
+ OP_DELETE = "DELETE"
31
+ OP_ADD = "ADD"
29
32
30
33
def set_handler (self , key , data ):
34
+ log_debug ("AdvertiseRouteMgr:: set handler" )
35
+ if not self .__set_handler_validate (key , data ):
36
+ return True
31
37
vrf , ip_prefix = self .split_key (key )
32
- self .add_route_advertisement (vrf , ip_prefix )
38
+ self .add_route_advertisement (vrf , ip_prefix , data )
33
39
34
40
return True
35
41
36
-
37
42
def del_handler (self , key ):
43
+ log_debug ("AdvertiseRouteMgr:: del handler" )
38
44
vrf , ip_prefix = self .split_key (key )
39
45
self .remove_route_advertisement (vrf , ip_prefix )
40
46
41
-
42
- def add_route_advertisement (self , vrf , ip_prefix ):
47
+ def __set_handler_validate (self , key , data ):
48
+ if data :
49
+ if ("profile" in data and data ["profile" ] in ROUTE_MAPS ) or data == {"" :"" }:
50
+ """
51
+ APP which config the data should be responsible to pass a valid IP prefix
52
+ """
53
+ return True
54
+
55
+ log_err ("BGPAdvertiseRouteMgr:: Invalid data %s for advertised route %s" % (data , key ))
56
+ return False
57
+
58
+ def add_route_advertisement (self , vrf , ip_prefix , data ):
43
59
if self .directory .path_exist ("CONFIG_DB" , swsscommon .CFG_DEVICE_METADATA_TABLE_NAME , "localhost/bgp_asn" ):
44
- if not self .advertised_routes .get (vrf , set ()):
60
+ if not self .advertised_routes .get (vrf , dict ()):
45
61
self .bgp_network_import_check_commands (vrf , self .OP_ADD )
46
- self .advertise_route_commands (ip_prefix , vrf , self .OP_ADD )
47
-
48
- self .advertised_routes .setdefault (vrf , set ()).add (ip_prefix )
62
+ self .advertise_route_commands (ip_prefix , vrf , self .OP_ADD , data )
49
63
64
+ self .advertised_routes .setdefault (vrf , dict ()).update ({ip_prefix : data })
50
65
51
66
def remove_route_advertisement (self , vrf , ip_prefix ):
52
- self .advertised_routes .setdefault (vrf , set ()).discard (ip_prefix )
53
- if not self .advertised_routes .get (vrf , set ()):
67
+ if ip_prefix not in self .advertised_routes .get (vrf , dict ()):
68
+ log_info ("BGPAdvertiseRouteMgr:: %s|%s does not exist" % (vrf , ip_prefix ))
69
+ return
70
+ self .advertised_routes .get (vrf , dict ()).pop (ip_prefix )
71
+ if not self .advertised_routes .get (vrf , dict ()):
54
72
self .advertised_routes .pop (vrf , None )
55
73
56
74
if self .directory .path_exist ("CONFIG_DB" , swsscommon .CFG_DEVICE_METADATA_TABLE_NAME , "localhost/bgp_asn" ):
57
- if not self .advertised_routes .get (vrf , set ()):
75
+ if not self .advertised_routes .get (vrf , dict ()):
58
76
self .bgp_network_import_check_commands (vrf , self .OP_DELETE )
59
77
self .advertise_route_commands (ip_prefix , vrf , self .OP_DELETE )
60
78
61
-
62
- def advertise_route_commands (self , ip_prefix , vrf , op ):
79
+ def advertise_route_commands (self , ip_prefix , vrf , op , data = None ):
63
80
is_ipv6 = TemplateFabric .is_ipv6 (ip_prefix )
64
81
bgp_asn = self .directory .get_slot ("CONFIG_DB" , swsscommon .CFG_DEVICE_METADATA_TABLE_NAME )["localhost" ]["bgp_asn" ]
65
82
66
83
cmd_list = []
67
- if vrf == ' default' :
84
+ if vrf == " default" :
68
85
cmd_list .append ("router bgp %s" % bgp_asn )
69
86
else :
70
87
cmd_list .append ("router bgp %s vrf %s" % (bgp_asn , vrf ))
71
88
72
89
cmd_list .append (" address-family %s unicast" % ("ipv6" if is_ipv6 else "ipv4" ))
73
- cmd_list .append (" %snetwork %s" % ('no ' if op == self .OP_DELETE else '' , ip_prefix ))
74
90
75
- self .cfg_mgr .push_list (cmd_list )
91
+ if data and "profile" in data :
92
+ cmd_list .append (" network %s route-map %s" % (ip_prefix , "%s_RM" % data ["profile" ]))
93
+ log_debug (
94
+ "BGPAdvertiseRouteMgr:: Update bgp %s network %s with route-map %s"
95
+ % (bgp_asn , vrf + "|" + ip_prefix , "%s_RM" % data ["profile" ])
96
+ )
97
+ else :
98
+ cmd_list .append (" %snetwork %s" % ("no " if op == self .OP_DELETE else "" , ip_prefix ))
99
+ log_debug (
100
+ "BGPAdvertiseRouteMgr:: %sbgp %s network %s"
101
+ % ("Remove " if op == self .OP_DELETE else "Update " , bgp_asn , vrf + "|" + ip_prefix )
102
+ )
76
103
104
+ self .cfg_mgr .push_list (cmd_list )
105
+ log_debug ("BGPAdvertiseRouteMgr::Done" )
77
106
78
107
def bgp_network_import_check_commands (self , vrf , op ):
79
108
bgp_asn = self .directory .get_slot ("CONFIG_DB" , swsscommon .CFG_DEVICE_METADATA_TABLE_NAME )["localhost" ]["bgp_asn" ]
80
109
cmd_list = []
81
- if vrf == ' default' :
110
+ if vrf == " default" :
82
111
cmd_list .append ("router bgp %s" % bgp_asn )
83
112
else :
84
113
cmd_list .append ("router bgp %s vrf %s" % (bgp_asn , vrf ))
85
- cmd_list .append (" %sbgp network import-check" % ('' if op == self .OP_DELETE else ' no ' ))
114
+ cmd_list .append (" %sbgp network import-check" % ("" if op == self .OP_DELETE else " no " ))
86
115
87
116
self .cfg_mgr .push_list (cmd_list )
88
117
89
-
90
118
def on_bgp_asn_change (self ):
91
119
if self .directory .path_exist ("CONFIG_DB" , swsscommon .CFG_DEVICE_METADATA_TABLE_NAME , "localhost/bgp_asn" ):
92
120
for vrf , ip_prefixes in self .advertised_routes .items ():
93
121
self .bgp_network_import_check_commands (vrf , self .OP_ADD )
94
122
for ip_prefix in ip_prefixes :
95
- self .add_route_advertisement (vrf , ip_prefix )
96
-
123
+ self .add_route_advertisement (vrf , ip_prefix , ip_prefixes [ip_prefix ])
97
124
98
125
@staticmethod
99
126
def split_key (key ):
@@ -102,7 +129,7 @@ def split_key(key):
102
129
:param key: key to split
103
130
:return: vrf name extracted from the key, ip prefix extracted from the key
104
131
"""
105
- if '|' not in key :
106
- return ' default' , key
132
+ if "|" not in key :
133
+ return " default" , key
107
134
else :
108
- return tuple (key .split ('|' , 1 ))
135
+ return tuple (key .split ("|" , 1 ))
0 commit comments