Skip to content

Commit d2c5d6e

Browse files
michael-koellermroethke
authored andcommitted
Add pfx_table wrapper class.
1 parent 62a3cb1 commit d2c5d6e

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

rtrlib.cdef

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,16 @@ void pfx_table_free(struct pfx_table *pfx_table);
457457
*/
458458
int pfx_table_add(struct pfx_table *pfx_table, const struct pfx_record *pfx_record);
459459

460+
/**
461+
* @brief Removes a pfx_record from a pfx_table.
462+
* @param[in] pfx_table pfx_table to use.
463+
* @param[in] pfx_record Record that will be removed.
464+
* @return PFX_SUCCESS On success.
465+
* @return PFX_ERROR On error.
466+
* @return PFX_RECORD_NOT_FOUND If pfx_records couldn't be found.
467+
*/
468+
int pfx_table_remove(struct pfx_table *pfx_table, const struct pfx_record *pfx_record);
469+
460470
/**
461471
* @brief Validates the origin of a BGP-Route.
462472
* @param[in] pfx_table pfx_table to use.

rtrlib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import logging
1111

12+
from .pfx_table import PfxTable
1213
from .rtr_manager import RTRManager, PfxvState
1314
from .manager_group import ManagerGroupStatus
1415

rtrlib/pfx_table.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# -*- coding: utf8 -*-
2+
"""
3+
rtrlib.rtr_manager
4+
------------------
5+
6+
"""
7+
8+
from __future__ import absolute_import, unicode_literals
9+
10+
11+
from .exceptions import PFXException
12+
from .rtr_manager import ValidationResult
13+
from .util import ip_str_to_addr
14+
15+
from _rtrlib import ffi, lib
16+
17+
18+
class PfxTable(object):
19+
"""
20+
Wrapper class around pfx_table.
21+
22+
"""
23+
24+
def __init__(self):
25+
# allocate pfx_table
26+
self.pfx_table = ffi.new('struct pfx_table *')
27+
# initialize it
28+
lib.pfx_table_init(self.pfx_table,
29+
ffi.NULL)
30+
self.closed = False
31+
32+
@staticmethod
33+
def _create_pfx_record(asn, ip, min_length, max_length):
34+
record = ffi.new('struct pfx_record *')
35+
lib.lrtr_ip_str_to_addr(ip.encode('ascii'), ffi.addressof(record, 'prefix'))
36+
37+
record.asn = asn
38+
record.min_len = min_length
39+
record.max_len = max_length
40+
record.socket = ffi.NULL
41+
42+
return record
43+
44+
def add_record(self, asn, ip, min_length, max_length):
45+
"""
46+
Add a BGP prefix to the table.
47+
48+
:param asn: autonomous system number
49+
:type asn: int
50+
51+
:param ip: ip address
52+
:type ip: str
53+
54+
:param min_length: minimum length of the subnet mask
55+
:type min_length: int
56+
57+
:param max_length: minimum length of the subnet mask
58+
:type max_length: int
59+
"""
60+
61+
record = self._create_pfx_record(asn, ip, min_length, max_length)
62+
63+
lib.pfx_table_add(self.pfx_table, record)
64+
65+
def remove_record(self, asn, ip, min_length, max_length):
66+
"""
67+
Add a BGP prefix to the table.
68+
69+
:param asn: autonomous system number
70+
:type asn: int
71+
72+
:param ip: ip address
73+
:type ip: str
74+
75+
:param min_length: minimum length of the subnet mask
76+
:type min_length: int
77+
78+
:param max_length: minimum length of the subnet mask
79+
:type max_length: int
80+
"""
81+
82+
record = self._create_pfx_record(asn, ip, min_length, max_length)
83+
84+
lib.pfx_table_remove(self.pfx_table, record)
85+
86+
def validate(self, asn, prefix, mask_len):
87+
"""
88+
Validate BGP prefix and returns state as ValidationResult object.
89+
The reason list in the returned result will be empty.
90+
91+
:param asn: autonomous system number
92+
:type asn: int
93+
94+
:param prefix: ip address
95+
:type prefix: str
96+
97+
:param mask_len: length of the subnet mask
98+
:type mask_len: int
99+
100+
:rtype: ValidationResult
101+
"""
102+
103+
result = ffi.new('enum pfxv_state *')
104+
105+
ret = lib.pfx_table_validate(self.pfx_table,
106+
asn,
107+
ip_str_to_addr(prefix),
108+
mask_len,
109+
result)
110+
111+
if ret == lib.PFX_ERROR:
112+
raise PFXException("An error occurred during validation")
113+
114+
return ValidationResult(prefix,
115+
mask_len,
116+
asn,
117+
result[0])
118+
119+
def validate_r(self, asn, prefix, mask_len):
120+
"""
121+
Validate BGP prefix and returns state as ValidationResult object.
122+
The reason list in the returned result will contain a list of Reason objects.
123+
124+
:param asn: autonomous system number
125+
:type asn: int
126+
127+
:param prefix: ip address
128+
:type prefix: str
129+
130+
:param mask_len: length of the subnet mask
131+
:type mask_len: int
132+
133+
:rtype: ValidationResult
134+
"""
135+
136+
result = ffi.new('enum pfxv_state *')
137+
138+
reason = ffi.new('struct pfx_record **')
139+
reason[0] = ffi.NULL
140+
reason_length = ffi.new('unsigned int *')
141+
reason_length[0] = 0
142+
143+
ret = lib.pfx_table_validate_r(self.pfx_table,
144+
reason,
145+
reason_length,
146+
asn,
147+
ip_str_to_addr(prefix),
148+
mask_len,
149+
result)
150+
151+
if ret == lib.PFX_ERROR:
152+
raise PFXException("An error occurred during validation")
153+
154+
return ValidationResult(prefix,
155+
mask_len,
156+
asn,
157+
result[0],
158+
reason,
159+
reason_length[0])
160+
161+
def close(self):
162+
if not self.closed:
163+
lib.pfx_table_free(self.pfx_table)
164+
self.closed = True
165+
166+
def __enter__(self):
167+
return self
168+
169+
def __del__(self):
170+
self.close()
171+
172+
def __exit__(self, exc_type, exc_val, exc_tb):
173+
self.close()
174+
return False

0 commit comments

Comments
 (0)