ifstate 1.13.5__py3-none-any.whl → 1.13.7__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.
ifstate/vrrp.py CHANGED
@@ -139,7 +139,7 @@ def vrrp_fifo(args_fifo, ifs_config):
139
139
 
140
140
  try:
141
141
  status_pattern = re.compile(
142
- r'(group|instance) "([^"]+)" (' + '|'.join(KEEPALIVED_STATES) + ')( \d+)?$', re.IGNORECASE)
142
+ r'(group|instance) "([^"]+)" (' + '|'.join(KEEPALIVED_STATES) + r')( \d+)?$', re.IGNORECASE)
143
143
 
144
144
  with open(args_fifo) as fifo:
145
145
  logger.debug("entering fifo loop...")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ifstate
3
- Version: 1.13.5
3
+ Version: 1.13.7
4
4
  Summary: Manage host interface settings in a declarative manner
5
5
  Home-page: https://ifstate.net/
6
6
  Author: Thomas Liske
@@ -1,9 +1,9 @@
1
1
  ifstate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  ifstate/ifstate.py,sha256=l6VxiAXWyoqj7T5J495gM5Nhn807f5pHmL8_kh1uJAc,8891
3
3
  ifstate/shell.py,sha256=7_JFpi4icr9MijynDzbb0v5mxhFsng6PCC4m3uQ255A,2177
4
- ifstate/vrrp.py,sha256=cXzQZ2v-QS56ZBS8raLM4GyCjPFtTV6tg_9Drkgul1k,5952
5
- ifstate-1.13.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
6
- libifstate/__init__.py,sha256=NfL3Ef-3vH3I56mR9MxZX3nQc3a7Asig0luDPBclokw,30950
4
+ ifstate/vrrp.py,sha256=FJ9b1eJseTtZFfknHU-xV68Qz7cPrRrc5PTcjUVj-fY,5953
5
+ ifstate-1.13.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
6
+ libifstate/__init__.py,sha256=dFqgv0fFecMsztHMh_IZnFyv2mOIyoM3KsmR13iCx5w,31132
7
7
  libifstate/exception.py,sha256=5i59BZdl56J_sNJbyU9n6uHuUNJEyDOO4FJ-neDn9Ds,2608
8
8
  libifstate/log.py,sha256=XVoZdwdQoWsjuupFIuG6OP0OrBpXpx7oqyAaUhQ-nJk,4553
9
9
  libifstate/util.py,sha256=WzbGKX78iWUunnZ-v_3OREmxMiYt7vVM_QyCgTcMYow,10802
@@ -14,24 +14,24 @@ libifstate/bpf/map.py,sha256=cLHNMvRBDNW2yVCEf3z242_oRdU0HqVbFEYVkKXng0w,10818
14
14
  libifstate/brport/__init__.py,sha256=NzdA8F4hr2se1bXKNnyKZbvOFlCWBq_cdjwsL1H0Y-o,2964
15
15
  libifstate/fdb/__init__.py,sha256=9dpL5n8ct3CaA-z8I6ZEkD3yL6yWJQeq3fpIe9pc2zw,6486
16
16
  libifstate/link/__init__.py,sha256=epVw6jY8exNeJZUmmUas91yJoeupfgIY7rthq7SGIIw,142
17
- libifstate/link/base.py,sha256=Si31tqRTRGnHusn1hRPLrfdEmeQqRyNP4aua1DlGc_Q,34319
17
+ libifstate/link/base.py,sha256=vGMQDgvLbIX4OF9YOMwttcRAOZeGvsIQqXEpKNdLJH4,34739
18
18
  libifstate/link/dsa.py,sha256=Y3axTtcym6YL1voKblxctx4PoKDZHzpteKQNnEBUrS8,264
19
19
  libifstate/link/physical.py,sha256=cJiq-MCfy-3XQoU-OxzgfPZZtu_pJ8u2ioJgn9VYdGk,560
20
20
  libifstate/link/tun.py,sha256=m55o5cwO3h3DCLofUR-68fM4ggLoTKElp6ZJ2LrJSCc,959
21
21
  libifstate/link/veth.py,sha256=V_jmQCizI5Vv8-pcsfldSfMRTn1knR11wZDZI_yXvks,2249
22
22
  libifstate/neighbour/__init__.py,sha256=FJJpbJvqnxvOEii6QDMYzW5jQDEbiEy71GQOEbqaS48,2463
23
- libifstate/netns/__init__.py,sha256=gh7WN-3ksL0jrrdZyMOIe3yV-VGrPqCqRvbJMKdHsoo,8909
23
+ libifstate/netns/__init__.py,sha256=Fip3g2P1Tt_12pLt8abHsMRjSLZVi5THd1RJYcm9zfM,8887
24
24
  libifstate/parser/__init__.py,sha256=byz1W0G7UewVc5FFie-ti3UZjGK3-75wHIaOeq0oySQ,88
25
25
  libifstate/parser/base.py,sha256=VFAo05O3tiKtI381LVUMYfsDTseMKoQGTfkgnEkm3H4,4770
26
26
  libifstate/parser/yaml.py,sha256=MC0kmwqt3P45z61fb_wfUqoj0iZyhFYkdPyr0UqMSZA,1415
27
- libifstate/routing/__init__.py,sha256=Hmj-LHBEtVXs5tlRzY8JS_C5qdnN3alD3cIznmzQ-rY,20469
27
+ libifstate/routing/__init__.py,sha256=fxDqDaNRcrb-8Lo6qH3UBifzJGymWwmMBXQSpMgyG0Y,22754
28
28
  libifstate/sysctl/__init__.py,sha256=EF52CdOOkVSUFR2t21A99KlG1-PjsD4qOiceQC4eI24,3074
29
29
  libifstate/tc/__init__.py,sha256=inPdampCOIr_4oKNB3awqMkW0Eh4fpPh9jvSba6sPVg,12092
30
30
  libifstate/wireguard/__init__.py,sha256=HEmGsrtIX8MEjxtMbqgzP-e2BIUicyfmcywnRE93lRQ,6579
31
31
  libifstate/xdp/__init__.py,sha256=X1xhEIGng7R5d5F4KsChykT2g6H-XBRWbWABijoYDQA,7208
32
32
  schema/ifstate.conf.schema.json,sha256=NOPeI8_r1jXvgAAJeBqz92ZACNvxskId3qMykj-sG7M,201292
33
- ifstate-1.13.5.dist-info/METADATA,sha256=7wXC-qOpR-GJ2ENCpWYZc7-FqaqEaIc98I39apFge_E,1598
34
- ifstate-1.13.5.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
35
- ifstate-1.13.5.dist-info/entry_points.txt,sha256=HF6jX7Uu_nF1Ly-J9uEPeiRapOxnM6LuHsb2y6Mt-k4,52
36
- ifstate-1.13.5.dist-info/top_level.txt,sha256=A7peI7aKBaM69fsiSPvMbL3rzTKZZr5qDxKC-pHMGdE,19
37
- ifstate-1.13.5.dist-info/RECORD,,
33
+ ifstate-1.13.7.dist-info/METADATA,sha256=mmhqlLk_amWU3IHFsUo7FWtaZF3sMLoZ0VZNACZra1M,1598
34
+ ifstate-1.13.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ ifstate-1.13.7.dist-info/entry_points.txt,sha256=HF6jX7Uu_nF1Ly-J9uEPeiRapOxnM6LuHsb2y6Mt-k4,52
36
+ ifstate-1.13.7.dist-info/top_level.txt,sha256=A7peI7aKBaM69fsiSPvMbL3rzTKZZr5qDxKC-pHMGdE,19
37
+ ifstate-1.13.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
libifstate/__init__.py CHANGED
@@ -48,7 +48,7 @@ import json
48
48
  import errno
49
49
  import logging
50
50
 
51
- __version__ = "1.13.5"
51
+ __version__ = "1.13.7"
52
52
 
53
53
 
54
54
  class IfState():
@@ -455,7 +455,7 @@ class IfState():
455
455
 
456
456
  # create and destroy namespaces to match config
457
457
  if not by_vrrp and self.namespaces is not None:
458
- prepare_netns(do_apply, self.namespaces.keys(), self.new_namespaces)
458
+ prepare_netns(do_apply, self.namespaces.keys(), self.new_namespaces, self.ignore.get('netns', []))
459
459
  logger.info("")
460
460
 
461
461
  # get link dependency tree
@@ -467,8 +467,10 @@ class IfState():
467
467
  cleanup_items = []
468
468
  for item in self.link_registry.registry:
469
469
  ifname = item.attributes['ifname']
470
- # items without a link are orphan - keep them if they match the ignore regex list...
471
- if item.link is None and not any(re.match(regex, ifname) for regex in self.ignore.get('ifname', [])):
470
+ # items without a link are orphan - keep them if they match the ignore (ifname|netns) regex list...
471
+ if item.link is None and \
472
+ not any(re.match(regex, ifname) for regex in self.ignore.get('ifname', [])) and \
473
+ not any(re.match(regex, item.netns.netns or '') for regex in self.ignore.get('netns', [])):
472
474
  # ...or are in a netns namespace while the config has no `namespaces` setting
473
475
  if self.namespaces is not None or item.netns.netns is None:
474
476
  if not had_cleanup:
libifstate/link/base.py CHANGED
@@ -452,11 +452,17 @@ class Link(ABC):
452
452
  netns_attr = "{}_netns".format(attr)
453
453
  netnsid_attr = "{}_netnsid".format(attr)
454
454
  if netns_attr in self.settings:
455
- # ToDo: throw exception for unknown netns
456
- (peer_ipr, peer_nsid) = self.netns.get_netnsid(self.settings[netns_attr])
457
- self.settings[netnsid_attr] = peer_nsid
458
- idx = next(iter(peer_ipr.link_lookup(
459
- ifname=self.settings[attr])), None)
455
+ # ignore *_netns settings if the netns is the same as the interface's one
456
+ # (there is no IFLA_LINK_NETNSID attribute in such cases)
457
+ if self.settings[netns_attr] != self.netns.netns:
458
+ # ToDo: throw exception for unknown netns
459
+ (peer_ipr, peer_nsid) = self.netns.get_netnsid(self.settings[netns_attr])
460
+ self.settings[netnsid_attr] = peer_nsid
461
+ idx = next(iter(peer_ipr.link_lookup(
462
+ ifname=self.settings[attr])), None)
463
+ else:
464
+ idx = next(iter(self.netns.ipr.link_lookup(
465
+ ifname=self.settings[attr])), None)
460
466
 
461
467
  del(self.settings[netns_attr])
462
468
  else:
@@ -59,10 +59,7 @@ class NetNameSpace():
59
59
  memo[id(self)] = result
60
60
  for k, v in self.__dict__.items():
61
61
  if k == 'ipr':
62
- if self.netns is None:
63
- setattr(result, k, IPRouteExt())
64
- else:
65
- setattr(result, k, NetNSExt(self.netns))
62
+ setattr(result, k, v)
66
63
  else:
67
64
  setattr(result, k, deepcopy(v, memo))
68
65
  return result
@@ -84,7 +81,7 @@ class NetNameSpace():
84
81
 
85
82
  return (peer_ipr, peer_nsid)
86
83
 
87
- def prepare_netns(do_apply, target_netns_list, new_netns_list):
84
+ def prepare_netns(do_apply, target_netns_list, new_netns_list, ignore_netns):
88
85
  logger.info("configure network namespaces...")
89
86
 
90
87
  # get mapping of netns names to lists of pids
@@ -97,14 +94,15 @@ def prepare_netns(do_apply, target_netns_list, new_netns_list):
97
94
  for name in sorted(names_set):
98
95
  # cleanup orphan netns
99
96
  if name not in target_netns_list:
100
- if name in ns_pids:
101
- logger.warning(
102
- 'pids: {}'.format(', '.join((str(x) for x in ns_pids[name]))),
103
- extra={'iface': name})
104
- logger.log_del(name)
105
-
106
- if do_apply:
107
- pyroute2.netns.remove(name)
97
+ if not any(re.match(regex, name) for regex in ignore_netns):
98
+ if name in ns_pids:
99
+ logger.warning(
100
+ 'pids: {}'.format(', '.join((str(x) for x in ns_pids[name]))),
101
+ extra={'iface': name})
102
+ logger.log_del(name)
103
+
104
+ if do_apply:
105
+ pyroute2.netns.remove(name)
108
106
 
109
107
  # create missing netns
110
108
  elif name not in current_netns_list or name in new_netns_list:
@@ -15,6 +15,147 @@ from socket import AF_INET, AF_INET6
15
15
  def route_matches(r1, r2, fields=('dst', 'priority', 'proto'), indent=None):
16
16
  return _matches(r1, r2, fields, indent)
17
17
 
18
+ def parse_route(route, implicit_defaults=True):
19
+ rt = {}
20
+
21
+ if implicit_defaults:
22
+ rt['type'] = route.get('type', 'unicast')
23
+
24
+ if 'to' in route:
25
+ dst = ip_network(route['to'])
26
+ rt['dst'] = dst.with_prefixlen
27
+ has_to = True
28
+ else:
29
+ has_to = False
30
+
31
+ for key, lookup in RT_LOOKUPS_DICT.items():
32
+ try:
33
+ if implicit_defaults:
34
+ rt[key] = route.get(key, RT_LOOKUPS_DEFAULTS[key])
35
+ rt[key] = lookup.lookup_id(rt[key])
36
+ else:
37
+ if key in route:
38
+ rt[key] = route[key]
39
+ rt[key] = lookup.lookup_id(rt[key])
40
+ except KeyError as err:
41
+ # mapping not available - catch exception and skip it
42
+ logger.warning('ignoring unknown %s "%s"', key, rt[key],
43
+ extra={'iface': rt['dst']})
44
+ rt[key] = RT_LOOKUPS_DEFAULTS[key]
45
+
46
+ if 'type' in rt and type(rt['type']) == str:
47
+ rt['type'] = rt_type[rt['type']]
48
+
49
+ if 'dev' in route:
50
+ rt['oif'] = route['dev']
51
+
52
+ if 'via' in route:
53
+ via = ip_address(route['via'])
54
+
55
+ if not has_to or via.version == dst.version:
56
+ rt['gateway'] = str(via)
57
+ else:
58
+ if via.version == 4:
59
+ rt['via'] = {
60
+ 'family': int(AF_INET),
61
+ 'addr': str(via),
62
+ }
63
+ else:
64
+ rt['via'] = {
65
+ 'family': int(AF_INET6),
66
+ 'addr': str(via),
67
+ }
68
+
69
+ if 'src' in route:
70
+ rt['prefsrc'] = route['src']
71
+
72
+ if 'preference' in route:
73
+ rt['priority'] = route['preference']
74
+ elif has_to and implicit_defaults:
75
+ if isinstance(dst, IPv6Network):
76
+ rt['priority'] = 1024
77
+ else:
78
+ rt['priority'] = 0
79
+
80
+ if 'vrrp' in route:
81
+ rt['_vrrp'] = route['vrrp']
82
+
83
+ return rt
84
+
85
+ def parse_routes(routes, implicit_defaults=True):
86
+ return [parse_route(route, implicit_defaults) for route in routes]
87
+
88
+ def parse_rule(rule, implicit_defaults=True):
89
+ ru = {}
90
+
91
+ if implicit_defaults:
92
+ ru['table'] = RTLookups.tables.lookup_id(rule.get('table', 254))
93
+ ru['protocol'] = RTLookups.protos.lookup_id(rule.get('proto', 0))
94
+ ru['tos'] = rule.get('tos', 0)
95
+ else:
96
+ if 'table' in rule:
97
+ ru['table'] = RTLookups.tables.lookup_id(rule['table'])
98
+ if 'proto' in rule:
99
+ ru['protocol'] = RTLookups.protos.lookup_id(rule['proto'])
100
+ if 'tos' in rule:
101
+ ru['tos'] = rule['tos']
102
+
103
+ if 'action' in rule and type(rule['action']) == str:
104
+ ru['action'] = {
105
+ "to_tbl": "FR_ACT_TO_TBL",
106
+ "unicast": "FR_ACT_UNICAST",
107
+ "blackhole": "FR_ACT_BLACKHOLE",
108
+ "unreachable": "FR_ACT_UNREACHABLE",
109
+ "prohibit": "FR_ACT_PROHIBIT",
110
+ "nat": "FR_ACT_NAT",
111
+ }.get(rule['action'], rule['action'])
112
+ elif implicit_defaults:
113
+ ru['action'] = "FR_ACT_TO_TBL"
114
+
115
+ if 'fwmark' in rule:
116
+ ru['fwmark'] = rule['fwmark']
117
+
118
+ if 'ipproto' in rule:
119
+ if type(rule['ipproto']) == str:
120
+ ru['ip_proto'] = socket.getprotobyname(rule['ipproto'])
121
+ else:
122
+ ru['ip_proto'] = rule['ipproto']
123
+
124
+ if 'to' in rule:
125
+ ru['dst'] = str(ip_network(rule['to']).network_address)
126
+ ru['dst_len'] = ip_network(rule['to']).prefixlen
127
+
128
+ if 'from' in rule:
129
+ if rule['from'] != "all":
130
+ ru['src'] = str(ip_interface(rule['from']).ip)
131
+ ru['src_len'] = ip_network(ip_interface(rule['from']).network).prefixlen
132
+ else:
133
+ ru['src'] = "0.0.0.0"
134
+ ru['src_len'] = 0
135
+
136
+ if 'iif' in rule:
137
+ ru['iifname'] = rule['iif']
138
+
139
+ if 'oif' in rule:
140
+ ru['oifname'] = rule['oif']
141
+
142
+ if 'priority' in rule:
143
+ ru['priority'] = rule['priority']
144
+
145
+ if 'vrrp' in rule:
146
+ ru['_vrrp'] = rule['vrrp']
147
+
148
+ if 'family' in rule:
149
+ assert rule['family'] in ("AF_INET", "inet", 2, "AF_INET6", "inet6", 10), "rule['family'] doesn't have a valid value. This should have already been rejected by the schema validation."
150
+ if rule['family'] in ("AF_INET", "inet", 2):
151
+ ru['family'] = AF_INET
152
+ elif rule['family'] in ("AF_INET6", "inet6", 10):
153
+ ru['family'] = AF_INET6
154
+
155
+ return ru
156
+
157
+ def parse_rules(rules, implicit_defaults=True):
158
+ return [parse_rule(rule, implicit_defaults) for rule in rules]
18
159
 
19
160
  def rule_matches(r1, r2, fields=('priority', 'iif', 'oif', 'dst', 'metric', 'protocol'), indent=None):
20
161
  return _matches(r1, r2, fields, indent)
@@ -133,64 +274,36 @@ class Tables(collections.abc.Mapping):
133
274
  def __len__(self):
134
275
  return len(self.tables)
135
276
 
136
- def add(self, route):
137
- dst = ip_network(route['to'])
138
- rt = {
139
- 'type': route.get('type', 'unicast'),
140
- 'dst': dst.with_prefixlen,
141
- }
142
-
143
- for key, lookup in RT_LOOKUPS_DICT.items():
144
- try:
145
- rt[key] = route.get(key, RT_LOOKUPS_DEFAULTS[key])
146
- rt[key] = lookup.lookup_id(rt[key])
147
- except KeyError as err:
148
- # mapping not available - catch exception and skip it
149
- logger.warning('ignoring unknown %s "%s"', key, rt[key],
150
- extra={'iface': rt['dst'], 'netns': self.netns})
151
- rt[key] = RT_LOOKUPS_DEFAULTS[key]
152
-
153
- if type(rt['type']) == str:
154
- rt['type'] = rt_type[rt['type']]
155
-
156
- if 'dev' in route:
157
- rt['oif'] = route['dev']
158
-
159
- if 'via' in route:
160
- via = ip_address(route['via'])
161
-
162
- if via.version == dst.version:
163
- rt['gateway'] = str(via)
164
- else:
165
- if via.version == 4:
166
- rt['via'] = {
167
- 'family': int(AF_INET),
168
- 'addr': str(via),
169
- }
170
- else:
171
- rt['via'] = {
172
- 'family': int(AF_INET6),
173
- 'addr': str(via),
174
- }
175
-
176
- if 'src' in route:
177
- rt['prefsrc'] = route['src']
277
+ def parse_ignores(self, ignores):
278
+ parsed = []
279
+ for ignore in ignores:
280
+ ignore = parse_route(ignore, False)
281
+
282
+ for attr in ['dev', 'oif', 'iif']:
283
+ if attr in ignore and type(ignore[attr]) == str:
284
+ idx = next(
285
+ iter(self.netns.ipr.link_lookup(ifname=ignore[attr])), None)
286
+ if idx is None:
287
+ logger.debug("{} '{}' is unknown".format(attr, ignore[attr]))
288
+ del ignore[attr]
289
+ else:
290
+ ignore[attr] = idx
291
+ parsed.append(ignore)
178
292
 
179
- if 'preference' in route:
180
- rt['priority'] = route['preference']
181
- elif isinstance(dst, IPv6Network):
182
- rt['priority'] = 1024
183
- else:
184
- rt['priority'] = 0
293
+ return parsed
185
294
 
186
- if 'vrrp' in route:
187
- rt['_vrrp'] = route['vrrp']
295
+ def add(self, route):
296
+ # convert config dict into IFLA keys and values
297
+ rt = parse_route(route)
188
298
 
299
+ # track route in the corresponding table
189
300
  if not rt['table'] in self.tables:
190
301
  self.tables[rt['table']] = []
191
302
  self.tables[rt['table']].append(rt)
192
303
 
193
304
  def show_routes(self, ignores):
305
+ ignores = self.parse_ignores(ignores)
306
+
194
307
  routes = []
195
308
  for route in self.netns.ipr.get_routes(family=AF_INET) + self.netns.ipr.get_routes(family=AF_INET6):
196
309
  # skip routes from local table
@@ -322,6 +435,8 @@ class Tables(collections.abc.Mapping):
322
435
  return routes
323
436
 
324
437
  def apply(self, ignores, do_apply, by_vrrp, vrrp_type, vrrp_name, vrrp_state):
438
+ ignores = self.parse_ignores(ignores)
439
+
325
440
  for table, croutes in self.tables.items():
326
441
  log_str = RTLookups.tables.lookup_str(table)
327
442
  if self.netns.netns != None:
@@ -413,53 +528,10 @@ class Rules():
413
528
  self.rules = []
414
529
 
415
530
  def add(self, rule):
416
- ru = {
417
- 'table': RTLookups.tables.lookup_id(rule.get('table', 254)),
418
- 'protocol': RTLookups.protos.lookup_id(rule.get('proto', 0)),
419
- 'tos': rule.get('tos', 0),
420
- }
421
-
422
- if 'action' in rule and type(rule['action']) == str:
423
- ru['action'] = {
424
- "to_tbl": "FR_ACT_TO_TBL",
425
- "unicast": "FR_ACT_UNICAST",
426
- "blackhole": "FR_ACT_BLACKHOLE",
427
- "unreachable": "FR_ACT_UNREACHABLE",
428
- "prohibit": "FR_ACT_PROHIBIT",
429
- "nat": "FR_ACT_NAT",
430
- }.get(rule['action'], rule['action'])
431
- else:
432
- ru['action'] = rule.get('action'.lower(), "FR_ACT_TO_TBL")
433
-
434
- if 'fwmark' in rule:
435
- ru['fwmark'] = rule['fwmark']
436
-
437
- if 'ipproto' in rule:
438
- if type(rule['ipproto']) == str:
439
- ru['ip_proto'] = socket.getprotobyname(rule['ipproto'])
440
- else:
441
- ru['ip_proto'] = rule['ipproto']
442
-
443
- if 'to' in rule:
444
- ru['dst'] = str(ip_network(rule['to']).network_address)
445
- ru['dst_len'] = ip_network(rule['to']).prefixlen
446
-
447
- if 'from' in rule:
448
- ru['src'] = str(ip_network(rule['from']).network_address)
449
- ru['src_len'] = ip_network(rule['from']).prefixlen
450
-
451
- if 'iif' in rule:
452
- ru['iifname'] = rule['iif']
453
-
454
- if 'oif' in rule:
455
- ru['oifname'] = rule['oif']
456
-
457
- if 'priority' in rule:
458
- ru['priority'] = rule['priority']
459
-
460
- if 'vrrp' in rule:
461
- ru['_vrrp'] = rule['vrrp']
531
+ # convert config dict into IFLA keys and values
532
+ ru = parse_rule(rule)
462
533
 
534
+ # track rule
463
535
  self.rules.append(ru)
464
536
 
465
537
  def kernel_rules(self):
@@ -491,14 +563,13 @@ class Rules():
491
563
  return rules
492
564
 
493
565
  def show_rules(self, ignores):
566
+ ignores = parse_rules(ignores, implicit_defaults=False)
567
+
494
568
  rules = []
495
569
  for rule in self.kernel_rules():
496
570
  # skip ignored routes
497
571
  ignore = False
498
572
  for irule in ignores:
499
- if 'proto' in irule:
500
- irule['protocol'] = irule['proto']
501
- del irule['proto']
502
573
  if rule_matches(rule, irule, irule.keys()):
503
574
  ignore = True
504
575
  break
@@ -534,6 +605,9 @@ class Rules():
534
605
  return rules
535
606
 
536
607
  def apply(self, ignores, do_apply, by_vrrp, vrrp_type, vrrp_name, vrrp_state):
608
+ ignores = parse_rules(ignores, implicit_defaults=False)
609
+
610
+ # get rules that are currently in the kernels list
537
611
  krules = self.kernel_rules()
538
612
  for rule in self.rules:
539
613
  log_str = '#{}'.format(rule['priority'])