Skip to content

Commit a95bfff

Browse files
author
Capirca Team
committed
Introduce new option to Capirca Arista traffic-policy generator:
- "destination_self" generates `destination prefix self unicast` match condition, which matches packets destined to the local router interfaces. This match condition is mutually exclusive to other `destination` conditions. PiperOrigin-RevId: 840347750
1 parent ba29dc9 commit a95bfff

4 files changed

Lines changed: 73 additions & 1 deletion

File tree

capirca/lib/arista_tp.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class AristaTpFragmentInV6Error(Error):
7070
pass
7171

7272

73+
class TooManyAddressAttributesError(Error):
74+
pass
75+
7376
class Config:
7477
"""config allows a configuration to be assembled easily.
7578
@@ -233,7 +236,7 @@ def __str__(self):
233236
self.term.hop_limit or self.term.port or self.term.protocol or
234237
self.term.protocol_except or self.term.source_address or
235238
self.term.source_address_exclude or self.term.source_port or
236-
self.term.source_prefix or self.term.ttl )
239+
self.term.source_prefix or self.term.ttl or self.term.destination_self)
237240

238241
# if the term name is default-* we will render this into the
239242
# appropriate default term name to be used in this filter.
@@ -276,6 +279,20 @@ def __str__(self):
276279
term=self.term.name, direction="source", af=self.term_type))
277280
return ""
278281

282+
# destination self
283+
if self.term.destination_self:
284+
if (
285+
self.term.destination_address
286+
or self.term.destination_address_exclude
287+
or self.term.destination_prefix
288+
):
289+
raise TooManyAddressAttributesError(
290+
"'destination_self', 'destination_address', "
291+
"'destination_address_exclude', and 'destination_prefix' "
292+
"are mutually exclusive."
293+
)
294+
term_block.append([MATCH_INDENT, "destination prefix self unicast", False])
295+
279296
# destination address
280297
dst_addr = self.term.GetAddressOfVersion("destination_address", term_af)
281298
dst_addr_ex = self.term.GetAddressOfVersion("destination_address_exclude",
@@ -771,6 +788,7 @@ def _BuildTokens(self):
771788
"destination_address_exclude",
772789
"destination_port",
773790
"destination_prefix",
791+
"destination_self",
774792
"dscp_set",
775793
"expiration",
776794
"fragment_offset",

capirca/lib/policy.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ def __init__(self, obj):
458458
self.destination_address = []
459459
self.destination_address_exclude = []
460460
self.destination_port = []
461+
self.destination_self = False
461462
self.destination_prefix = []
462463
self.filter_term = None
463464
self.forwarding_class = []
@@ -796,6 +797,8 @@ def __str__(self):
796797
' destination_address_exclude: %s'
797798
% self._SortAddressesByFamily('destination_address_exclude')
798799
)
800+
if self.destination_self:
801+
ret_str.append(' destination_self: true')
799802
if self.destination_tag:
800803
ret_str.append(' destination_tag: %s' % self.destination_tag)
801804
if self.target_resources:
@@ -1120,6 +1123,9 @@ def __eq__(self, other):
11201123
if sorted(self.destination_zone) != sorted(other.destination_zone):
11211124
return False
11221125

1126+
if self.destination_self != other.destination_self:
1127+
return False
1128+
11231129
return True
11241130

11251131
def __ne__(self, other):
@@ -1335,6 +1341,9 @@ def AddObject(self, obj):
13351341
self.source_zone.append(x.value)
13361342
elif x.var_type is VarType.DZONE:
13371343
self.destination_zone.append(x.value)
1344+
elif x.var_type is VarType.DESTINATION_SELF:
1345+
if x.value == 'true':
1346+
self.destination_self = True
13381347
elif x.var_type is VarType.FORTIGATE_APPLICATION_ID:
13391348
self.fortigate_application_id.append(x.value)
13401349
else:
@@ -1444,6 +1453,9 @@ def AddObject(self, obj):
14441453
self.target_service_accounts.append(obj.value)
14451454
elif obj.var_type is VarType.FILTER_TERM:
14461455
self.filter_term = obj.value
1456+
elif obj.var_type is VarType.DESTINATION_SELF:
1457+
if obj.value == 'true':
1458+
self.destination_self = True
14471459
elif obj.var_type is VarType.FORTIGATE_APPLICATION_ID:
14481460
self.fortigate_application_id.append(obj.value)
14491461
else:
@@ -1816,6 +1828,7 @@ class VarType:
18161828
POLICE_BURST = 74
18171829
POLICE_PPS = 75
18181830
FORTIGATE_APPLICATION_ID = 76
1831+
DESTINATION_SELF = 77
18191832

18201833
def __init__(self, var_type, value):
18211834
self.var_type = var_type
@@ -1993,6 +2006,7 @@ def __ne__(self, other):
19932006
'DSCP_SET',
19942007
'DTAG',
19952008
'DZONE',
2009+
'DESTINATION_SELF',
19962010
'ENCAPSULATE',
19972011
'ESCAPEDSTRING',
19982012
'ETHER_TYPE',
@@ -2085,6 +2099,7 @@ def __ne__(self, other):
20852099
'destination-prefix': 'DPFX',
20862100
'destination-prefix-except': 'EDPFX',
20872101
'destination-port': 'DPORT',
2102+
'destination-self': 'DESTINATION_SELF',
20882103
'destination-tag': 'DTAG',
20892104
'destination-zone': 'DZONE',
20902105
'dscp-except': 'DSCP_EXCEPT',
@@ -2283,6 +2298,7 @@ def p_term_spec(p):
22832298
"""term_spec : term_spec action_spec
22842299
22852300
| term_spec addr_spec
2301+
| term_spec destination_self_spec
22862302
| term_spec restrict_address_family_spec
22872303
| term_spec comment_spec
22882304
| term_spec counter_spec
@@ -2545,6 +2561,11 @@ def p_dscp_except_spec(p):
25452561
p[0].append(VarType(VarType.DSCP_EXCEPT, dscp))
25462562

25472563

2564+
def p_destination_self_spec(p):
2565+
"""destination_self_spec : DESTINATION_SELF ':' ':' STRING"""
2566+
p[0] = VarType(VarType.DESTINATION_SELF, p[4])
2567+
2568+
25482569
def p_exclude_spec(p):
25492570
"""exclude_spec : SADDREXCLUDE ':' ':' one_or_more_strings
25502571

capirca/lib/policy_simple.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ class DestinationPrefixExcept(Field):
170170
"""A destination-prefix-except field."""
171171

172172

173+
class DestinationSelf(Field):
174+
"""A destination-self field."""
175+
176+
173177
class DestinationTag(Field):
174178
"""A destination tag field."""
175179

@@ -368,6 +372,7 @@ class ApplicationID(Field):
368372
'destination-port': DestinationPort,
369373
'destination-prefix': DestinationPrefix,
370374
'destination-prefix-except': DestinationPrefixExcept,
375+
'destination-self': DestinationSelf,
371376
'destination-tag': DestinationTag,
372377
'destination-zone': DestinationZone,
373378
'dscp-match': DscpMatch,

tests/lib/arista_tp_test.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,19 @@
271271
traffic-class:: 4
272272
}
273273
"""
274+
GOOD_DST_SELF_TERM = """
275+
term good-dst-self-term {
276+
destination-self:: true
277+
action:: accept
278+
}
279+
"""
280+
BAD_DST_SELF_ADDR_TERM = """
281+
term bad-dst-self-addr-term {
282+
destination-address:: SOME_HOST
283+
destination-self:: true
284+
action:: accept
285+
}
286+
"""
274287
NEXT_HOP_GROUP_TERM = """
275288
term next-hop-group-term {
276289
protocol:: tcp
@@ -638,6 +651,7 @@
638651
"destination_address_exclude",
639652
"destination_port",
640653
"destination_prefix",
654+
"destination_self",
641655
"dscp_set",
642656
"expiration",
643657
"fragment_offset",
@@ -1401,6 +1415,20 @@ def testAnyMixed(self):
14011415
self.assertIn("match ipv6-ANY_MIXED ipv6", output, output)
14021416
self.assertIn("destination prefix 2001:4860:4860::8844/128", output, output)
14031417

1418+
def testDestinationSelf(self):
1419+
atp = arista_tp.AristaTrafficPolicy(
1420+
policy.ParsePolicy(GOOD_HEADER + GOOD_DST_SELF_TERM, self.naming),
1421+
EXP_INFO)
1422+
output = str(atp)
1423+
self.assertIn("destination prefix self unicast", output, output)
1424+
1425+
def testDestinationSelfAddrConflict(self):
1426+
self.naming.GetNetAddr.return_value = [nacaddr.IP("10.0.0.0/8")]
1427+
atp = arista_tp.AristaTrafficPolicy(
1428+
policy.ParsePolicy(GOOD_HEADER + BAD_DST_SELF_ADDR_TERM, self.naming),
1429+
EXP_INFO)
1430+
self.assertRaises(arista_tp.TooManyAddressAttributesError, str, atp)
1431+
14041432
def testDscpSet(self):
14051433
self.naming.GetNetAddr.side_effect = [[
14061434
nacaddr.IP("8.8.4.4"),

0 commit comments

Comments
 (0)