@@ -14,8 +14,11 @@ class BGPAllowListMgr(Manager):
14
14
ALLOW_ADDRESS_PL_NAME_TMPL = "ALLOW_ADDRESS_%d_%s" # template for a name for the ALLOW_ADDRESS prefix-list ???
15
15
EMPTY_COMMUNITY = "empty"
16
16
PL_NAME_TMPL = "PL_ALLOW_LIST_DEPLOYMENT_ID_%d_COMMUNITY_%s_V%s"
17
+ PL_NAME_TMPL_WITH_NEIGH = "PL_ALLOW_LIST_DEPLOYMENT_ID_%d_NEIGHBOR_%s_COMMUNITY_%s_V%s"
17
18
COMMUNITY_NAME_TMPL = "COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_%d_COMMUNITY_%s"
19
+ COMMUNITY_NAME_TMPL_WITH_NEIGH = "COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_%d_NEIGHBOR_%s_COMMUNITY_%s"
18
20
RM_NAME_TMPL = "ALLOW_LIST_DEPLOYMENT_ID_%d_V%s"
21
+ RM_NAME_TMPL_WITH_NEIGH = "ALLOW_LIST_DEPLOYMENT_ID_%d_NEIGHBOR_%s_V%s"
19
22
ROUTE_MAP_ENTRY_WITH_COMMUNITY_START = 10
20
23
ROUTE_MAP_ENTRY_WITH_COMMUNITY_END = 29990
21
24
ROUTE_MAP_ENTRY_WITHOUT_COMMUNITY_START = 30000
@@ -38,7 +41,7 @@ def __init__(self, common_objs, db, table):
38
41
db ,
39
42
table ,
40
43
)
41
- self .key_re = re .compile (r"^DEPLOYMENT_ID\|\d+\|\S+$|^DEPLOYMENT_ID\|\d+$" )
44
+ self .key_re = re .compile (r"^DEPLOYMENT_ID\|\d+\|\S+$|^DEPLOYMENT_ID\|\d+$|^DEPLOYMENT_ID\|\d+\|\S+\|NEIGHBOR_TYPE\|\S+$|^DEPLOYMENT_ID\|\d+\|NEIGHBOR_TYPE\|\S+ " )
42
45
self .enabled = self .__get_enabled ()
43
46
self .prefix_match_tag = self .__get_routemap_tag ()
44
47
self .__load_constant_lists ()
@@ -55,8 +58,14 @@ def set_handler(self, key, data):
55
58
return True
56
59
if not self .__set_handler_validate (key , data ):
57
60
return True
58
- key = key .replace ("DEPLOYMENT_ID|" , "" )
59
- deployment_id , community_value = key .split ('|' , 1 ) if '|' in key else (key , BGPAllowListMgr .EMPTY_COMMUNITY )
61
+ if 'NEIGHBOR_TYPE' in key :
62
+ keys = key .split ('|NEIGHBOR_TYPE|' , 1 )
63
+ deployment_id = keys [0 ].replace ("DEPLOYMENT_ID|" , "" )
64
+ neighbor_type , community_value = keys [1 ].split ('|' , 1 ) if '|' in keys [1 ] else (keys [1 ], BGPAllowListMgr .EMPTY_COMMUNITY )
65
+ else :
66
+ key = key .replace ("DEPLOYMENT_ID|" , "" )
67
+ deployment_id , community_value = key .split ('|' , 1 ) if '|' in key else (key , BGPAllowListMgr .EMPTY_COMMUNITY )
68
+ neighbor_type = ''
60
69
deployment_id = int (deployment_id )
61
70
prefixes_v4 = []
62
71
prefixes_v6 = []
@@ -65,7 +74,7 @@ def set_handler(self, key, data):
65
74
if "prefixes_v6" in data :
66
75
prefixes_v6 = str (data ['prefixes_v6' ]).split ("," )
67
76
default_action_community = self .__get_default_action_community (data )
68
- self .__update_policy (deployment_id , community_value , prefixes_v4 , prefixes_v6 , default_action_community )
77
+ self .__update_policy (deployment_id , community_value , prefixes_v4 , prefixes_v6 , default_action_community , neighbor_type )
69
78
return True
70
79
71
80
def __set_handler_validate (self , key , data ):
@@ -85,13 +94,13 @@ def __set_handler_validate(self, key, data):
85
94
prefixes_v6 = []
86
95
if "prefixes_v4" in data :
87
96
prefixes_v4 = str (data ["prefixes_v4" ]).split ("," )
88
- if not all (TemplateFabric .is_ipv4 (prefix ) for prefix in prefixes_v4 ):
97
+ if not all (TemplateFabric .is_ipv4 (re . split ( 'ge|le' , prefix )[ 0 ] ) for prefix in prefixes_v4 ):
89
98
arguments = "prefixes_v4" , str (data ["prefixes_v4" ])
90
99
log_err ("BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid input[%s]:'%s'" % arguments )
91
100
return False
92
101
if "prefixes_v6" in data :
93
102
prefixes_v6 = str (data ["prefixes_v6" ]).split ("," )
94
- if not all (TemplateFabric .is_ipv6 (prefix ) for prefix in prefixes_v6 ):
103
+ if not all (TemplateFabric .is_ipv6 (re . split ( 'ge|le' , prefix )[ 0 ] ) for prefix in prefixes_v6 ):
95
104
arguments = "prefixes_v6" , str (data ["prefixes_v6" ])
96
105
log_err ("BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid input[%s]:'%s'" % arguments )
97
106
return False
@@ -113,10 +122,18 @@ def del_handler(self, key):
113
122
return
114
123
if not self .__del_handler_validate (key ):
115
124
return
116
- key = key .replace ('DEPLOYMENT_ID|' , '' )
117
- deployment_id , community = key .split ('|' , 1 ) if '|' in key else (key , BGPAllowListMgr .EMPTY_COMMUNITY )
125
+
126
+ if 'NEIGHBOR_TYPE' in key :
127
+ keys = key .split ('|NEIGHBOR_TYPE|' , 1 )
128
+ deployment_id = keys [0 ].replace ("DEPLOYMENT_ID|" , "" )
129
+ neighbor_type , community_value = keys [1 ].split ('|' , 1 ) if '|' in keys [1 ] else (keys [1 ], BGPAllowListMgr .EMPTY_COMMUNITY )
130
+ else :
131
+ key = key .replace ("DEPLOYMENT_ID|" , "" )
132
+ deployment_id , community_value = key .split ('|' , 1 ) if '|' in key else (key , BGPAllowListMgr .EMPTY_COMMUNITY )
133
+ neighbor_type = ''
134
+
118
135
deployment_id = int (deployment_id )
119
- self .__remove_policy (deployment_id , community )
136
+ self .__remove_policy (deployment_id , community_value , neighbor_type )
120
137
121
138
def __del_handler_validate (self , key ):
122
139
"""
@@ -129,7 +146,7 @@ def __del_handler_validate(self, key):
129
146
return False
130
147
return True
131
148
132
- def __update_policy (self , deployment_id , community_value , prefixes_v4 , prefixes_v6 , default_action ):
149
+ def __update_policy (self , deployment_id , community_value , prefixes_v4 , prefixes_v6 , default_action , neighbor_type ):
133
150
"""
134
151
Update "allow list" policy with parameters
135
152
:param deployment_id: deployment id which policy will be changed
@@ -139,12 +156,13 @@ def __update_policy(self, deployment_id, community_value, prefixes_v4, prefixes_
139
156
:param default_action: the default action for the policy. should be either 'permit' or 'deny'
140
157
"""
141
158
# update all related entries with the information
142
- info = deployment_id , community_value , str (prefixes_v4 ), str (prefixes_v6 )
159
+ info = deployment_id , community_value , str (prefixes_v4 ), str (prefixes_v6 ), neighbor_type
143
160
msg = "BGPAllowListMgr::Updating 'Allow list' policy."
144
161
msg += " deployment_id '%s'. community: '%s'"
145
162
msg += " prefix_v4 '%s'. prefix_v6: '%s'"
163
+ msg += " neighbor_type %s"
146
164
log_info (msg % info )
147
- names = self .__generate_names (deployment_id , community_value )
165
+ names = self .__generate_names (deployment_id , community_value , neighbor_type )
148
166
self .cfg_mgr .update ()
149
167
cmds = []
150
168
cmds += self .__update_prefix_list (self .V4 , names ['pl_v4' ], prefixes_v4 )
@@ -156,14 +174,14 @@ def __update_policy(self, deployment_id, community_value, prefixes_v4, prefixes_
156
174
cmds += self .__update_default_route_map_entry (names ['rm_v6' ], default_action )
157
175
if cmds :
158
176
self .cfg_mgr .push_list (cmds )
159
- peer_groups = self .__find_peer_group_by_deployment_id (deployment_id )
177
+ peer_groups = self .__find_peer_group (deployment_id , neighbor_type )
160
178
self .cfg_mgr .restart_peer_groups (peer_groups )
161
179
log_debug ("BGPAllowListMgr::__update_policy. The peers configuration scheduled for updates" )
162
180
else :
163
181
log_debug ("BGPAllowListMgr::__update_policy. Nothing to update" )
164
182
log_info ("BGPAllowListMgr::Done" )
165
183
166
- def __remove_policy (self , deployment_id , community_value ):
184
+ def __remove_policy (self , deployment_id , community_value , neighbor_type ):
167
185
"""
168
186
Remove "allow list" policy for given deployment_id and community_value
169
187
:param deployment_id: deployment id which policy will be removed
@@ -177,7 +195,7 @@ def __remove_policy(self, deployment_id, community_value):
177
195
log_info (msg % info )
178
196
179
197
default_action = self .__get_default_action_community ()
180
- names = self .__generate_names (deployment_id , community_value )
198
+ names = self .__generate_names (deployment_id , community_value , neighbor_type )
181
199
self .cfg_mgr .update ()
182
200
cmds = []
183
201
cmds += self .__remove_allow_route_map_entry (self .V4 , names ['pl_v4' ], names ['community' ], names ['rm_v4' ])
@@ -189,34 +207,50 @@ def __remove_policy(self, deployment_id, community_value):
189
207
cmds += self .__update_default_route_map_entry (names ['rm_v6' ], default_action )
190
208
if cmds :
191
209
self .cfg_mgr .push_list (cmds )
192
- peer_groups = self .__find_peer_group_by_deployment_id (deployment_id )
210
+ peer_groups = self .__find_peer_group (deployment_id , neighbor_type )
193
211
self .cfg_mgr .restart_peer_groups (peer_groups )
194
212
log_debug ("BGPAllowListMgr::__remove_policy. 'Allow list' policy was scheduled for removal" )
195
213
else :
196
214
log_debug ("BGPAllowListMgr::__remove_policy. Nothing to remove" )
197
215
log_info ('BGPAllowListMgr::Done' )
198
216
199
217
@staticmethod
200
- def __generate_names (deployment_id , community_value ):
218
+ def __generate_names (deployment_id , community_value , neighbor_type ):
201
219
"""
202
220
Generate prefix-list names for a given peer_ip and community value
203
221
:param deployment_id: deployment_id for which we're going to filter prefixes
204
222
:param community_value: community, which we want to use to filter prefixes
205
223
:return: a dictionary with names
206
224
"""
207
- if community_value == BGPAllowListMgr .EMPTY_COMMUNITY :
208
- community_name = BGPAllowListMgr .EMPTY_COMMUNITY
225
+ if neighbor_type == '' :
226
+ if community_value == BGPAllowListMgr .EMPTY_COMMUNITY :
227
+ community_name = BGPAllowListMgr .EMPTY_COMMUNITY
228
+ else :
229
+ community_name = BGPAllowListMgr .COMMUNITY_NAME_TMPL % (deployment_id , community_value )
230
+ names = {
231
+ "pl_v4" : BGPAllowListMgr .PL_NAME_TMPL % (deployment_id , community_value , '4' ),
232
+ "pl_v6" : BGPAllowListMgr .PL_NAME_TMPL % (deployment_id , community_value , '6' ),
233
+ "rm_v4" : BGPAllowListMgr .RM_NAME_TMPL % (deployment_id , '4' ),
234
+ "rm_v6" : BGPAllowListMgr .RM_NAME_TMPL % (deployment_id , '6' ),
235
+ "community" : community_name ,
236
+ 'neigh_type' : neighbor_type ,
237
+ }
238
+ arguments = deployment_id , community_value , str (names )
239
+ log_debug ("BGPAllowListMgr::__generate_names. deployment_id: %d, community: %s. names: %s" % arguments )
209
240
else :
210
- community_name = BGPAllowListMgr .COMMUNITY_NAME_TMPL % (deployment_id , community_value )
211
- names = {
212
- "pl_v4" : BGPAllowListMgr .PL_NAME_TMPL % (deployment_id , community_value , '4' ),
213
- "pl_v6" : BGPAllowListMgr .PL_NAME_TMPL % (deployment_id , community_value , '6' ),
214
- "rm_v4" : BGPAllowListMgr .RM_NAME_TMPL % (deployment_id , '4' ),
215
- "rm_v6" : BGPAllowListMgr .RM_NAME_TMPL % (deployment_id , '6' ),
216
- "community" : community_name ,
217
- }
218
- arguments = deployment_id , community_value , str (names )
219
- log_debug ("BGPAllowListMgr::__generate_names. deployment_id: %d, community: %s. names: %s" % arguments )
241
+ if community_value == BGPAllowListMgr .EMPTY_COMMUNITY :
242
+ community_name = BGPAllowListMgr .EMPTY_COMMUNITY
243
+ else :
244
+ community_name = BGPAllowListMgr .COMMUNITY_NAME_TMPL_WITH_NEIGH % (deployment_id , neighbor_type , community_value )
245
+ names = {
246
+ "pl_v4" : BGPAllowListMgr .PL_NAME_TMPL_WITH_NEIGH % (deployment_id , neighbor_type , community_value , '4' ),
247
+ "pl_v6" : BGPAllowListMgr .PL_NAME_TMPL_WITH_NEIGH % (deployment_id , neighbor_type , community_value , '6' ),
248
+ "rm_v4" : BGPAllowListMgr .RM_NAME_TMPL_WITH_NEIGH % (deployment_id , neighbor_type , '4' ),
249
+ "rm_v6" : BGPAllowListMgr .RM_NAME_TMPL_WITH_NEIGH % (deployment_id , neighbor_type , '6' ),
250
+ "community" : community_name ,
251
+ }
252
+ arguments = deployment_id , neighbor_type , community_value , str (names )
253
+ log_debug ("BGPAllowListMgr::__generate_names. deployment_id: %d, neighbor_type: %s, community: %s. names: %s" % arguments )
220
254
return names
221
255
222
256
def __update_prefix_list (self , af , pl_name , allow_list ):
@@ -630,7 +664,7 @@ def __get_routemap_tag(self):
630
664
return prefix_match_tag
631
665
632
666
@staticmethod
633
- def __get_peer_group_to_restart (deployment_id , pg_2_rm , rm_2_call ):
667
+ def __get_peer_group_to_restart (deployment_id , pg_2_rm , rm_2_call , neighbor_type ):
634
668
"""
635
669
Get peer_groups which are assigned to deployment_id
636
670
:deployment_id: deployment_id number
@@ -639,14 +673,17 @@ def __get_peer_group_to_restart(deployment_id, pg_2_rm, rm_2_call):
639
673
:rm_2_call: a dictionary: key - name of a route-map, value - name of a route-map call defined for the route-map
640
674
"""
641
675
ret = set ()
642
- target_allow_list_prefix = 'ALLOW_LIST_DEPLOYMENT_ID_%d_V' % deployment_id
676
+ if neighbor_type == '' :
677
+ target_allow_list_prefix = 'ALLOW_LIST_DEPLOYMENT_ID_%d_V' % deployment_id
678
+ else :
679
+ target_allow_list_prefix = 'ALLOW_LIST_DEPLOYMENT_ID_%d_NEIGHBOR_%s_V' % (deployment_id , neighbor_type )
643
680
for peer_group , route_map in pg_2_rm .items ():
644
681
if route_map in rm_2_call :
645
682
if rm_2_call [route_map ].startswith (target_allow_list_prefix ):
646
683
ret .add (peer_group )
647
684
return list (ret )
648
685
649
- def __find_peer_group_by_deployment_id (self , deployment_id ):
686
+ def __find_peer_group (self , deployment_id , neighbor_type ):
650
687
"""
651
688
Deduce peer-group names which are connected to devices with requested deployment_id
652
689
:param deployment_id: deployment_id number
@@ -656,7 +693,7 @@ def __find_peer_group_by_deployment_id(self, deployment_id):
656
693
peer_groups = self .__extract_peer_group_names ()
657
694
pg_2_rm = self .__get_peer_group_to_route_map (peer_groups )
658
695
rm_2_call = self .__get_route_map_calls (set (pg_2_rm .values ()))
659
- ret = self .__get_peer_group_to_restart (deployment_id , pg_2_rm , rm_2_call )
696
+ ret = self .__get_peer_group_to_restart (deployment_id , pg_2_rm , rm_2_call , neighbor_type )
660
697
return list (ret )
661
698
662
699
def __get_enabled (self ):
@@ -706,11 +743,14 @@ def __to_prefix_list(self, af, allow_list):
706
743
res = []
707
744
prefix_mask_default = 32 if af == self .V4 else 128
708
745
for prefix in allow_list :
709
- prefix_mask = int (prefix .split ("/" )[1 ])
710
- if prefix_mask == prefix_mask_default :
746
+ if 'le' in prefix or 'ge' in prefix :
711
747
res .append ("permit %s" % prefix )
712
748
else :
713
- res .append ("permit %s le %d" % (prefix , prefix_mask_default ))
749
+ prefix_mask = int (prefix .split ("/" )[1 ])
750
+ if prefix_mask == prefix_mask_default :
751
+ res .append ("permit %s" % prefix )
752
+ else :
753
+ res .append ("permit %s le %d" % (prefix , prefix_mask_default ))
714
754
return res
715
755
716
756
def __af_to_family (self , af ):
0 commit comments