annet 1.1.1__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of annet might be problematic. Click here for more details.

@@ -14,7 +14,7 @@ from .entities import (
14
14
  AsPathFilter, IpPrefixList, CommunityList, CommunityLogic, CommunityType,
15
15
  mangle_united_community_list_name, PrefixListNameGenerator,
16
16
  )
17
- from .prefix_lists import get_used_prefix_lists, new_prefix_list_name_generator
17
+
18
18
 
19
19
  FRR_RESULT_MAP = {
20
20
  ResultType.ALLOW: "permit",
@@ -51,12 +51,6 @@ class CumulusPolicyGenerator(ABC):
51
51
  def get_prefix_lists(self, device: Any) -> Sequence[IpPrefixList]:
52
52
  raise NotImplementedError()
53
53
 
54
- def get_used_prefix_lists(self, device: Any, name_generator: PrefixListNameGenerator) -> Sequence[IpPrefixList]:
55
- return get_used_prefix_lists(
56
- prefix_lists=self.get_prefix_lists(device),
57
- name_generator=name_generator,
58
- )
59
-
60
54
  @abstractmethod
61
55
  def get_community_lists(self, device: Any) -> list[CommunityList]:
62
56
  raise NotImplementedError()
@@ -66,8 +60,9 @@ class CumulusPolicyGenerator(ABC):
66
60
  raise NotImplementedError
67
61
 
68
62
  def generate_cumulus_rpl(self, device: Any) -> Iterator[Sequence[str]]:
63
+ prefix_lists = self.get_prefix_lists(device)
69
64
  policies = self.get_policies(device)
70
- prefix_list_name_generator = new_prefix_list_name_generator(policies)
65
+ prefix_list_name_generator = PrefixListNameGenerator(prefix_lists, policies)
71
66
 
72
67
  communities = {c.name: c for c in self.get_community_lists(device)}
73
68
  yield from self._cumulus_as_path_filters(device, policies)
@@ -89,60 +84,46 @@ class CumulusPolicyGenerator(ABC):
89
84
 
90
85
  def _cumulus_prefix_list(
91
86
  self,
92
- name: str,
93
87
  ip_type: Literal["ipv6", "ip"],
94
- match: PrefixMatchValue,
95
88
  plist: IpPrefixList,
96
89
  ) -> Iterable[Sequence[str]]:
97
- for i, prefix in enumerate(plist.members):
98
- addr_mask = ip_interface(prefix)
90
+ for i, m in enumerate(plist.members):
91
+ ge, le = m.or_longer
99
92
  yield (
100
93
  ip_type,
101
94
  "prefix-list",
102
- name,
95
+ plist.name,
103
96
  f"seq {i * 5 + 5}",
104
- "permit", f"{addr_mask.ip}/{addr_mask.network.prefixlen}",
97
+ "permit", str(m.prefix),
105
98
  ) + (
106
- ("ge", str(match.greater_equal)) if match.greater_equal is not None else ()
99
+ ("ge", str(ge)) if ge is not None else ()
107
100
  ) + (
108
- ("le", str(match.less_equal)) if match.less_equal is not None else ()
101
+ ("le", str(le)) if le is not None else ()
109
102
  )
110
103
 
111
104
  def _cumulus_prefix_lists(
112
105
  self, device: Any,
113
106
  policies: list[RoutingPolicy],
114
- prefix_list_name_generator: PrefixListNameGenerator,
107
+ name_generator: PrefixListNameGenerator,
115
108
  ) -> Iterable[Sequence[str]]:
116
- plists = {p.name: p for p in self.get_used_prefix_lists(device, prefix_list_name_generator)}
117
- if not plists.values():
118
- return
119
-
120
- precessed_names = set()
109
+ processed_names = set()
121
110
  for policy in policies:
122
111
  for statement in policy.statements:
123
112
  cond: SingleCondition[PrefixMatchValue]
124
113
  for cond in statement.match.find_all(MatchField.ip_prefix):
125
114
  for name in cond.value.names:
126
- mangled_name = prefix_list_name_generator.get_prefix_name(
127
- name=name,
128
- greater_equal=cond.value.greater_equal,
129
- less_equal=cond.value.less_equal,
130
- )
131
- if mangled_name in precessed_names:
115
+ plist = name_generator.get_prefix(name, cond.value)
116
+ if plist.name in processed_names:
132
117
  continue
133
- yield from self._cumulus_prefix_list(mangled_name, "ip", cond.value, plists[name])
134
- precessed_names.add(mangled_name)
118
+ yield from self._cumulus_prefix_list("ip", plist)
119
+ processed_names.add(plist.name)
135
120
  for cond in statement.match.find_all(MatchField.ipv6_prefix):
136
121
  for name in cond.value.names:
137
- mangled_name = prefix_list_name_generator.get_prefix_name(
138
- name=name,
139
- greater_equal=cond.value.greater_equal,
140
- less_equal=cond.value.less_equal,
141
- )
142
- if mangled_name in precessed_names:
122
+ plist = name_generator.get_prefix(name, cond.value)
123
+ if plist.name in processed_names:
143
124
  continue
144
- yield from self._cumulus_prefix_list(mangled_name, "ipv6", cond.value, plists[name])
145
- precessed_names.add(mangled_name)
125
+ yield from self._cumulus_prefix_list("ipv6", plist)
126
+ processed_names.add(plist.name)
146
127
  yield "!"
147
128
 
148
129
  def get_used_united_community_lists(
@@ -231,7 +212,7 @@ class CumulusPolicyGenerator(ABC):
231
212
  self,
232
213
  device: Any,
233
214
  condition: SingleCondition[Any],
234
- prefix_list_name_generator: PrefixListNameGenerator,
215
+ name_generator: PrefixListNameGenerator,
235
216
  ) -> Iterator[Sequence[str]]:
236
217
  if condition.field == MatchField.community:
237
218
  for comm_name in self._get_match_community_names(condition):
@@ -251,21 +232,13 @@ class CumulusPolicyGenerator(ABC):
251
232
  return
252
233
  if condition.field == MatchField.ip_prefix:
253
234
  for name in condition.value.names:
254
- mangled_name = prefix_list_name_generator.get_prefix_name(
255
- name=name,
256
- greater_equal=condition.value.greater_equal,
257
- less_equal=condition.value.less_equal,
258
- )
259
- yield "match", "ip address prefix-list", mangled_name
235
+ plist = name_generator.get_prefix(name, condition.value)
236
+ yield "match", "ip address prefix-list", plist.name
260
237
  return
261
238
  if condition.field == MatchField.ipv6_prefix:
262
239
  for name in condition.value.names:
263
- mangled_name = prefix_list_name_generator.get_prefix_name(
264
- name=name,
265
- greater_equal=condition.value.greater_equal,
266
- less_equal=condition.value.less_equal,
267
- )
268
- yield "match", "ipv6 address prefix-list", mangled_name
240
+ plist = name_generator.get_prefix(name, condition.value)
241
+ yield "match", "ipv6 address prefix-list", plist.name
269
242
  return
270
243
  if condition.operator is not ConditionOperator.EQ:
271
244
  raise NotImplementedError(
@@ -1,8 +1,10 @@
1
- from collections import defaultdict
1
+ from ipaddress import IPv4Network, IPv6Network, ip_network
2
2
  from collections.abc import Sequence
3
3
  from dataclasses import dataclass
4
4
  from enum import Enum
5
- from typing import Optional
5
+ from typing import Optional, List
6
+
7
+ from annet.rpl import RoutingPolicy, PrefixMatchValue, OrLonger
6
8
 
7
9
 
8
10
  class CommunityLogic(Enum):
@@ -40,10 +42,48 @@ class AsPathFilter:
40
42
  filters: Sequence[str]
41
43
 
42
44
 
43
- @dataclass(frozen=True)
45
+ @dataclass
46
+ class IpPrefixListMember:
47
+ prefix: IPv4Network | IPv6Network
48
+ or_longer: OrLonger = (None, None)
49
+
50
+ def __post_init__(self):
51
+ self.prefix = ip_network(self.prefix)
52
+
53
+
54
+ @dataclass
44
55
  class IpPrefixList:
45
56
  name: str
46
- members: Sequence[str]
57
+ members: list[IpPrefixListMember]
58
+
59
+ def __post_init__(self):
60
+ for (i, m) in enumerate(self.members):
61
+ if isinstance(m, str):
62
+ self.members[i] = IpPrefixListMember(m)
63
+
64
+
65
+ def ip_prefix_list(
66
+ name: str,
67
+ members_or_str: Sequence[IpPrefixListMember | str],
68
+ or_longer: OrLonger = (None, None),
69
+ ) -> IpPrefixList:
70
+ members: List[IpPrefixListMember] = []
71
+ for m in members_or_str:
72
+ if isinstance(m, str):
73
+ m = IpPrefixListMember(
74
+ prefix=ip_network(m),
75
+ or_longer=or_longer,
76
+ )
77
+ elif m.or_longer == (None, None):
78
+ m = IpPrefixListMember(
79
+ prefix=m.prefix,
80
+ or_longer=or_longer,
81
+ )
82
+ members.append(m)
83
+ return IpPrefixList(
84
+ name=name,
85
+ members=members,
86
+ )
47
87
 
48
88
 
49
89
  def arista_well_known_community(community: str) -> str:
@@ -58,26 +98,29 @@ def mangle_united_community_list_name(values: Sequence[str]) -> str:
58
98
 
59
99
 
60
100
  class PrefixListNameGenerator:
61
- def __init__(self):
62
- self._prefix_lists = defaultdict(set)
63
-
64
- def add_prefix(self, name: str, greater_equal: Optional[int], less_equal: Optional[int]) -> None:
65
- self._prefix_lists[name].add((greater_equal, less_equal))
66
-
67
- def is_used(self, name: str):
68
- return name in self._prefix_lists
69
-
70
- def get_prefix_name(self, name: str, greater_equal: Optional[int], less_equal: Optional[int]) -> str:
71
- if len(self._prefix_lists[name]) == 1:
72
- return name
73
- if greater_equal is less_equal is None:
74
- return name
75
- if greater_equal is None:
76
- ge_str = "unset"
77
- else:
78
- ge_str = str(greater_equal)
79
- if less_equal is None:
80
- le_str = "unset"
81
- else:
82
- le_str = str(less_equal)
83
- return f"{name}_{ge_str}_{le_str}"
101
+ def __init__(self, prefix_lists: Sequence[IpPrefixList], policies: Sequence[RoutingPolicy]):
102
+ self._prefix_lists = {x.name: x for x in prefix_lists}
103
+ self._policies = {x.name: x for x in policies} # this is here for a later use ~azryve@
104
+
105
+ def get_prefix(self, name: str, match: PrefixMatchValue) -> IpPrefixList:
106
+ orig_prefix = self._prefix_lists[name]
107
+ override_name: Optional[str] = None
108
+ override_orlonger: Optional[OrLonger] = None
109
+
110
+ if any(match.or_longer):
111
+ ge, le = match.or_longer
112
+ ge_str = "unset" if ge is None else str(ge)
113
+ le_str = "unset" if le is None else str(le)
114
+ override_name = f"{orig_prefix.name}_{ge_str}_{le_str}"
115
+ override_orlonger = match.or_longer
116
+
117
+ return IpPrefixList(
118
+ name=override_name or name,
119
+ members=[
120
+ IpPrefixListMember(
121
+ x.prefix,
122
+ or_longer=override_orlonger or x.or_longer,
123
+ )
124
+ for x in orig_prefix.members
125
+ ],
126
+ )
@@ -12,8 +12,9 @@ from annet.rpl.statement_builder import AsPathActionValue, NextHopActionValue, T
12
12
  from annet.rpl_generators.entities import (
13
13
  arista_well_known_community,
14
14
  CommunityList, RDFilter, PrefixListNameGenerator, CommunityLogic, mangle_united_community_list_name,
15
+ IpPrefixList,
15
16
  )
16
- from annet.rpl_generators.prefix_lists import new_prefix_list_name_generator
17
+
17
18
 
18
19
  HUAWEI_MATCH_COMMAND_MAP: dict[str, str] = {
19
20
  MatchField.as_path_filter: "as-path-filter {option_value}",
@@ -62,6 +63,10 @@ ARISTA_THEN_COMMAND_MAP: dict[str, str] = {
62
63
  class RoutingPolicyGenerator(PartialGenerator, ABC):
63
64
  TAGS = ["policy", "rpl", "routing"]
64
65
 
66
+ @abstractmethod
67
+ def get_prefix_lists(self, device: Any) -> list[IpPrefixList]:
68
+ raise NotImplementedError()
69
+
65
70
  @abstractmethod
66
71
  def get_policies(self, device: Any) -> list[RoutingPolicy]:
67
72
  raise NotImplementedError()
@@ -87,7 +92,7 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
87
92
  condition: SingleCondition[Any],
88
93
  communities: dict[str, CommunityList],
89
94
  rd_filters: dict[str, RDFilter],
90
- prefix_name_generator: PrefixListNameGenerator,
95
+ name_generator: PrefixListNameGenerator,
91
96
  ) -> Iterator[Sequence[str]]:
92
97
  if condition.field == MatchField.community:
93
98
  if condition.operator is ConditionOperator.HAS:
@@ -136,21 +141,13 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
136
141
  return
137
142
  if condition.field == MatchField.ip_prefix:
138
143
  for name in condition.value.names:
139
- mangled_name = prefix_name_generator.get_prefix_name(
140
- name=name,
141
- greater_equal=condition.value.greater_equal,
142
- less_equal=condition.value.less_equal,
143
- )
144
- yield "if-match", "ip-prefix", mangled_name
144
+ plist = name_generator.get_prefix(name, condition.value)
145
+ yield "if-match", "ip-prefix", plist.name
145
146
  return
146
147
  if condition.field == MatchField.ipv6_prefix:
147
148
  for name in condition.value.names:
148
- mangled_name = prefix_name_generator.get_prefix_name(
149
- name=name,
150
- greater_equal=condition.value.greater_equal,
151
- less_equal=condition.value.less_equal,
152
- )
153
- yield "if-match", "ipv6 address prefix-list", mangled_name
149
+ plist = name_generator.get_prefix(name, condition.value)
150
+ yield "if-match", "ipv6 address prefix-list", plist.name
154
151
  return
155
152
  if condition.field == MatchField.as_path_length:
156
153
  if condition.operator is ConditionOperator.EQ:
@@ -353,10 +350,11 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
353
350
  yield "goto next-node"
354
351
 
355
352
  def run_huawei(self, device):
353
+ prefix_lists = self.get_prefix_lists(device)
356
354
  policies = self.get_policies(device)
357
355
  communities = {c.name: c for c in self.get_community_lists(device)}
358
356
  rd_filters = {f.name: f for f in self.get_rd_filters(device)}
359
- prefix_name_generator = new_prefix_list_name_generator(policies)
357
+ prefix_name_generator = PrefixListNameGenerator(prefix_lists, policies)
360
358
 
361
359
  for policy in self.get_policies(device):
362
360
  for statement in policy.statements:
@@ -383,7 +381,7 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
383
381
  condition: SingleCondition[Any],
384
382
  communities: dict[str, CommunityList],
385
383
  rd_filters: dict[str, RDFilter],
386
- prefix_name_generator: PrefixListNameGenerator,
384
+ name_generator: PrefixListNameGenerator,
387
385
  ) -> Iterator[Sequence[str]]:
388
386
  if condition.field == MatchField.community:
389
387
  if condition.operator is ConditionOperator.HAS_ANY:
@@ -436,21 +434,13 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
436
434
  return
437
435
  if condition.field == MatchField.ip_prefix:
438
436
  for name in condition.value.names:
439
- mangled_name = prefix_name_generator.get_prefix_name(
440
- name=name,
441
- greater_equal=condition.value.greater_equal,
442
- less_equal=condition.value.less_equal,
443
- )
444
- yield "match", "ip address prefix-list", mangled_name
437
+ plist = name_generator.get_prefix(name, condition.value)
438
+ yield "match", "ip address prefix-list", plist.name
445
439
  return
446
440
  if condition.field == MatchField.ipv6_prefix:
447
441
  for name in condition.value.names:
448
- mangled_name = prefix_name_generator.get_prefix_name(
449
- name=name,
450
- greater_equal=condition.value.greater_equal,
451
- less_equal=condition.value.less_equal,
452
- )
453
- yield "match", "ipv6 address prefix-list", mangled_name
442
+ plist = name_generator.get_prefix(name, condition.value)
443
+ yield "match", "ipv6 address prefix-list", plist.name
454
444
  return
455
445
  if condition.field == MatchField.as_path_length:
456
446
  if condition.operator is ConditionOperator.EQ:
@@ -492,12 +482,15 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
492
482
  yield "set", "community community-list", *action.value.replaced
493
483
  else:
494
484
  yield "set", "community", "none"
495
- for community_name in action.value.added:
496
- yield "set", "community community-list", community_name, "additive"
497
- for community_name in action.value.removed:
498
- community = communities[community_name]
499
- for comm_value in community.members:
500
- yield "set community", arista_well_known_community(comm_value), "delete"
485
+ if action.value.added:
486
+ yield "set", "community community-list", *action.value.added, "additive"
487
+ if action.value.removed:
488
+ members = [
489
+ arista_well_known_community(member)
490
+ for community_name in action.value.removed
491
+ for member in communities[community_name].members
492
+ ]
493
+ yield "set community", *members, "delete"
501
494
 
502
495
  def _arista_then_large_community(
503
496
  self,
@@ -520,10 +513,10 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
520
513
  first = False
521
514
  else:
522
515
  yield "set", "large-community large-community-list", community_name, "additive"
523
- for community_name in action.value.added:
524
- yield "set", "large-community large-community-list", community_name, "additive"
525
- for community_name in action.value.removed:
526
- yield "set large-community large-community-list", community_name, "delete"
516
+ if action.value.added:
517
+ yield "set", "large-community large-community-list", *action.value.added, "additive"
518
+ if action.value.removed:
519
+ yield "set large-community large-community-list", *action.value.removed, "delete"
527
520
 
528
521
  def _arista_then_extcommunity_rt(
529
522
  self,
@@ -533,14 +526,20 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
533
526
  ) -> Iterator[Sequence[str]]:
534
527
  if action.value.replaced is not None:
535
528
  raise NotImplementedError("Extcommunity_rt replace is not supported for arista")
536
- for community_name in action.value.added:
537
- community = communities[community_name]
538
- for comm_value in community.members:
539
- yield "set", "extcommunity rt", comm_value, "additive"
540
- for community_name in action.value.removed:
541
- community = communities[community_name]
542
- for comm_value in community.members:
543
- yield "set extcommunity rt", comm_value, "delete"
529
+ if action.value.added:
530
+ members = [
531
+ f"rt {member}"
532
+ for community_name in action.value.removed
533
+ for member in communities[community_name].members
534
+ ]
535
+ yield "set", "extcommunity", *members, "additive"
536
+ if action.value.removed:
537
+ members = [
538
+ f"rt {member}"
539
+ for community_name in action.value.removed
540
+ for member in communities[community_name].members
541
+ ]
542
+ yield "set extcommunity", *members, "delete"
544
543
 
545
544
  def _arista_then_extcommunity_soo(
546
545
  self,
@@ -550,14 +549,20 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
550
549
  ) -> Iterator[Sequence[str]]:
551
550
  if action.value.replaced is not None:
552
551
  raise NotImplementedError("Extcommunity_soo replace is not supported for arista")
553
- for community_name in action.value.added:
554
- community = communities[community_name]
555
- for comm_value in community.members:
556
- yield "set", "extcommunity soo", comm_value, "additive"
557
- for community_name in action.value.removed:
558
- community = communities[community_name]
559
- for comm_value in community.members:
560
- yield "set", "extcommunity soo", comm_value, "delete"
552
+ if action.value.added:
553
+ members = [
554
+ f"soo {member}"
555
+ for community_name in action.value.removed
556
+ for member in communities[community_name].members
557
+ ]
558
+ yield "set", "extcommunity", *members, "additive"
559
+ if action.value.removed:
560
+ members = [
561
+ f"soo {member}"
562
+ for community_name in action.value.removed
563
+ for member in communities[community_name].members
564
+ ]
565
+ yield "set", "extcommunity", *members, "delete"
561
566
 
562
567
  def _arista_then_as_path(
563
568
  self,
@@ -675,8 +680,9 @@ class RoutingPolicyGenerator(PartialGenerator, ABC):
675
680
  yield "continue"
676
681
 
677
682
  def run_arista(self, device):
683
+ prefix_lists = self.get_prefix_lists(device)
678
684
  policies = self.get_policies(device)
679
- prefix_name_generator = new_prefix_list_name_generator(policies)
685
+ prefix_name_generator = PrefixListNameGenerator(prefix_lists, policies)
680
686
  communities = {c.name: c for c in self.get_community_lists(device)}
681
687
  rd_filters = {f.name: f for f in self.get_rd_filters(device)}
682
688
 
@@ -8,26 +8,6 @@ from annet.rpl import PrefixMatchValue, MatchField, SingleCondition, RoutingPoli
8
8
  from .entities import IpPrefixList, PrefixListNameGenerator
9
9
 
10
10
 
11
- def get_used_prefix_lists(
12
- prefix_lists: Sequence[IpPrefixList], name_generator: PrefixListNameGenerator,
13
- ) -> list[IpPrefixList]:
14
- return [c for c in prefix_lists if name_generator.is_used(c.name)]
15
-
16
-
17
- def new_prefix_list_name_generator(policies: list[RoutingPolicy]) -> PrefixListNameGenerator:
18
- name_gen = PrefixListNameGenerator()
19
- for policy in policies:
20
- for statement in policy.statements:
21
- condition: SingleCondition[PrefixMatchValue]
22
- for condition in statement.match.find_all(MatchField.ipv6_prefix):
23
- for name in condition.value.names:
24
- name_gen.add_prefix(name, condition.value.greater_equal, condition.value.less_equal)
25
- for condition in statement.match.find_all(MatchField.ip_prefix):
26
- for name in condition.value.names:
27
- name_gen.add_prefix(name, condition.value.greater_equal, condition.value.less_equal)
28
- return name_gen
29
-
30
-
31
11
  class PrefixListFilterGenerator(PartialGenerator, ABC):
32
12
  TAGS = ["policy", "rpl", "routing"]
33
13
 
@@ -39,12 +19,6 @@ class PrefixListFilterGenerator(PartialGenerator, ABC):
39
19
  def get_prefix_lists(self, device: Any) -> Sequence[IpPrefixList]:
40
20
  raise NotImplementedError()
41
21
 
42
- def get_used_prefix_lists(self, device: Any, name_generator: PrefixListNameGenerator) -> Sequence[IpPrefixList]:
43
- return get_used_prefix_lists(
44
- prefix_lists=self.get_prefix_lists(device),
45
- name_generator=name_generator,
46
- )
47
-
48
22
  # huawei
49
23
  def acl_huawei(self, _):
50
24
  return r"""
@@ -54,57 +28,48 @@ class PrefixListFilterGenerator(PartialGenerator, ABC):
54
28
 
55
29
  def _huawei_prefix_list(
56
30
  self,
57
- name: str,
58
31
  prefix_type: Literal["ipv6-prefix", "ip-prefix"],
59
- match: PrefixMatchValue,
60
32
  plist: IpPrefixList,
61
33
  ) -> Iterable[Sequence[str]]:
62
- for i, prefix in enumerate(plist.members):
63
- addr_mask = ip_interface(prefix)
34
+ for i, m in enumerate(plist.members):
35
+ ge, le = m.or_longer
64
36
  yield (
65
37
  "ip",
66
38
  prefix_type,
67
- name,
39
+ plist.name,
68
40
  f"index {i * 5 + 5}",
69
41
  "permit",
70
- str(addr_mask.ip).upper(),
71
- str(addr_mask.network.prefixlen),
42
+ str(m.prefix.network_address).upper(),
43
+ str(m.prefix.prefixlen),
72
44
  ) + (
73
- ("greater-equal", str(match.greater_equal)) if match.greater_equal is not None else ()
45
+ ("greater-equal", str(ge)) if ge is not None else ()
74
46
  ) + (
75
- ("less-equal", str(match.less_equal)) if match.less_equal is not None else ()
47
+ ("less-equal", str(le)) if le is not None else ()
76
48
  )
77
49
 
78
50
  def run_huawei(self, device: Any):
51
+ prefix_lists = self.get_prefix_lists(device)
79
52
  policies = self.get_policies(device)
80
- name_generator = new_prefix_list_name_generator(policies)
81
- plists = {p.name: p for p in self.get_used_prefix_lists(device, name_generator)}
82
- precessed_names = set()
53
+
54
+ name_generator = PrefixListNameGenerator(prefix_lists, policies)
55
+ processed_names = set()
83
56
  for policy in policies:
84
57
  for statement in policy.statements:
85
58
  cond: SingleCondition[PrefixMatchValue]
86
59
  for cond in statement.match.find_all(MatchField.ip_prefix):
87
60
  for name in cond.value.names:
88
- mangled_name = name_generator.get_prefix_name(
89
- name=name,
90
- greater_equal=cond.value.greater_equal,
91
- less_equal=cond.value.less_equal,
92
- )
93
- if mangled_name in precessed_names:
61
+ plist = name_generator.get_prefix(name, cond.value)
62
+ if plist.name in processed_names:
94
63
  continue
95
- yield from self._huawei_prefix_list(mangled_name, "ip-prefix", cond.value, plists[name])
96
- precessed_names.add(mangled_name)
64
+ yield from self._huawei_prefix_list("ip-prefix", plist)
65
+ processed_names.add(plist.name)
97
66
  for cond in statement.match.find_all(MatchField.ipv6_prefix):
98
67
  for name in cond.value.names:
99
- mangled_name = name_generator.get_prefix_name(
100
- name=name,
101
- greater_equal=cond.value.greater_equal,
102
- less_equal=cond.value.less_equal,
103
- )
104
- if mangled_name in precessed_names:
68
+ plist = name_generator.get_prefix(name, cond.value)
69
+ if plist.name in processed_names:
105
70
  continue
106
- yield from self._huawei_prefix_list(mangled_name, "ipv6-prefix", cond.value, plists[name])
107
- precessed_names.add(mangled_name)
71
+ yield from self._huawei_prefix_list("ipv6-prefix", plist)
72
+ processed_names.add(plist.name)
108
73
 
109
74
  # arista
110
75
  def acl_arista(self, _):
@@ -117,51 +82,41 @@ class PrefixListFilterGenerator(PartialGenerator, ABC):
117
82
 
118
83
  def _arista_prefix_list(
119
84
  self,
120
- name: str,
121
85
  prefix_type: Literal["ipv6", "ip"],
122
- match: PrefixMatchValue,
123
86
  plist: IpPrefixList,
124
87
  ) -> Iterable[Sequence[str]]:
125
- with self.block(prefix_type, "prefix-list", name):
126
- for i, prefix in enumerate(plist.members):
127
- addr_mask = ip_interface(prefix)
88
+ with self.block(prefix_type, "prefix-list", plist.name):
89
+ for i, m in enumerate(plist.members):
90
+ ge, le = m.or_longer
128
91
  yield (
129
92
  f"seq {i * 10 + 10}",
130
93
  "permit",
131
- addr_mask.with_prefixlen,
94
+ str(m.prefix),
132
95
  ) + (
133
- ("ge", str(match.greater_equal)) if match.greater_equal is not None else ()
96
+ ("ge", str(ge)) if ge is not None else ()
134
97
  ) + (
135
- ("le", str(match.less_equal)) if match.less_equal is not None else ()
98
+ ("le", str(le)) if le is not None else ()
136
99
  )
137
100
 
138
101
  def run_arista(self, device: Any):
102
+ prefix_lists = self.get_prefix_lists(device)
139
103
  policies = self.get_policies(device)
140
- name_generator = new_prefix_list_name_generator(policies)
141
- plists = {p.name: p for p in self.get_used_prefix_lists(device, name_generator)}
142
- precessed_names = set()
104
+ name_generator = PrefixListNameGenerator(prefix_lists, policies)
105
+ processed_names = set()
143
106
  for policy in policies:
144
107
  for statement in policy.statements:
145
108
  cond: SingleCondition[PrefixMatchValue]
146
109
  for cond in statement.match.find_all(MatchField.ip_prefix):
147
110
  for name in cond.value.names:
148
- mangled_name = name_generator.get_prefix_name(
149
- name=name,
150
- greater_equal=cond.value.greater_equal,
151
- less_equal=cond.value.less_equal,
152
- )
153
- if mangled_name in precessed_names:
111
+ plist = name_generator.get_prefix(name, cond.value)
112
+ if plist.name in processed_names:
154
113
  continue
155
- yield from self._arista_prefix_list(mangled_name, "ip", cond.value, plists[name])
156
- precessed_names.add(mangled_name)
114
+ yield from self._arista_prefix_list("ip", plist)
115
+ processed_names.add(plist.name)
157
116
  for cond in statement.match.find_all(MatchField.ipv6_prefix):
158
117
  for name in cond.value.names:
159
- mangled_name = name_generator.get_prefix_name(
160
- name=name,
161
- greater_equal=cond.value.greater_equal,
162
- less_equal=cond.value.less_equal,
163
- )
164
- if mangled_name in precessed_names:
118
+ plist = name_generator.get_prefix(name, cond.value)
119
+ if plist.name in processed_names:
165
120
  continue
166
- yield from self._arista_prefix_list(mangled_name, "ipv6", cond.value, plists[name])
167
- precessed_names.add(mangled_name)
121
+ yield from self._arista_prefix_list("ipv6", plist)
122
+ processed_names.add(plist.name)