3 Script to add LISP mappings to ODL. Currently it only supports the
4 RPC interface. Support for RESTCONF is planned in a future release.
6 Use `./mapping_blaster.py --help` to see options
8 Code inspired from `flow_config_blaster.py` by Jan Medved
18 __author__ = "Lori Jakab"
19 __copyright__ = "Copyright (c) 2014, Cisco Systems, Inc."
20 __credits__ = ["Jan Medved"]
21 __license__ = "New-style BSD"
22 __email__ = "lojakab@cisco.com"
26 class MappingRPCBlaster(object):
27 putheaders = {"Content-type": "application/json"}
28 getheaders = {"Accept": "application/json"}
30 RPC_URL_LI = "restconf/operations/lfm-mapping-database:"
31 RPC_URL_BE = "restconf/operations/odl-mappingservice:"
34 # Template for adding mappings
35 add_mapping_template = {
40 "authoritative": True,
42 "address-type": "ietf-lisp-address-types:ipv4-prefix-afi",
43 "ipv4-prefix": "10.0.0.0/32",
47 "locator-id": "ipv4:172.16.0.0",
50 "multicastPriority": 255,
56 "address-type": "ietf-lisp-address-types:ipv4-afi",
65 # Template for getting mappings
66 get_mapping_template = {"input": {"eid": {"ipv4-prefix": "10.0.0.0"}}}
68 def __init__(self, host, port, start_eid, mask, start_rloc, nmappings, v):
71 :param host: The host running ODL where we want to send the RPCs
72 :param port: The RESTCONF port on the ODL host
73 :param start_eid: The starting EID for adding mappings as an IPv4
75 :param mask: The network mask for the EID prefixes to be added
76 :param start_rloc: The starting RLOC for the locators in the
77 mappings as an IPv4 literal
78 :param nmappings: The number of mappings to be generated
79 :param v: Version of the ODL instance (since the RPC URL changed
80 from Lithium to Beryllium
82 self.session = requests.Session()
85 self.start_eid = netaddr.IPAddress(start_eid)
87 self.start_rloc = netaddr.IPAddress(start_rloc)
88 self.nmappings = nmappings
89 if v == "Li" or v == "li":
90 print("Using the Lithium RPC URL")
91 rpc_url = self.RPC_URL_LI
93 print("Using the Beryllium and later RPC URL")
94 rpc_url = self.RPC_URL_BE
96 self.post_url_template = "http://" + self.host + ":" + self.port + "/" + rpc_url
98 def mapping_from_tpl(self, eid, mask, rloc):
99 """Create an add-mapping RPC input dictionary from the mapping template
101 :param eid: Replace the default EID in the template with this one
102 :param mask: Replace the default mask in the template with this one
103 :param rloc: Replace the default RLOC in the template with this one
105 :return dict: mapping - template modified with the arguments
107 mapping = copy.deepcopy(self.add_mapping_template["input"]["mapping-record"])
108 mapping["eid"]["ipv4-prefix"] = str(netaddr.IPAddress(eid)) + "/" + mask
109 mapping["LocatorRecord"][0]["locator-id"] = "ipv4:" + str(
110 netaddr.IPAddress(rloc)
112 mapping["LocatorRecord"][0]["rloc"]["ipv4"] = str(netaddr.IPAddress(rloc))
115 def send_rpc(self, session, method, body):
116 """Send an HTTP POST to the RPC URL and return the status code
118 :param session: The HTTP session handle
119 :param method: "add" or "del"ete mapping
120 :param body: the JSON body to be sent
122 :return int: status_code - HTTP status code
124 rpc_url = self.post_url_template + method
128 headers=self.putheaders,
130 auth=("admin", "admin"),
131 timeout=self.TIMEOUT,
135 def add_n_mappings(self):
136 """Add self.nmappings mappings to ODL"""
137 rpc = dict(self.add_mapping_template)
138 increment = pow(2, 32 - int(self.mask))
139 for i in range(self.nmappings):
140 rpc["input"]["mapping-record"] = self.mapping_from_tpl(
141 self.start_eid + i * increment, self.mask, self.start_rloc + i
143 rpc_json = json.dumps(rpc)
144 self.send_rpc(self.session, "add-mapping", rpc_json)
147 def get_n_mappings(self):
148 """Retrieve self.nmappings mappings from ODL"""
149 rpc = dict(self.get_mapping_template)
150 increment = pow(2, 32 - int(self.mask))
151 for i in range(self.nmappings):
152 eid = self.start_eid + i * increment
153 rpc["input"]["eid"]["ipv4-prefix"] = (
154 str(netaddr.IPAddress(eid)) + "/" + self.mask
156 rpc_json = json.dumps(rpc)
157 self.send_rpc(self.session, "get-mapping", rpc_json)
161 if __name__ == "__main__":
162 parser = argparse.ArgumentParser(
163 description="Add simple IPv4 \
164 prefix-to-IPv4 locator LISP mappings to OpenDaylight"
170 help='Operating mode, can be "add" or "get" \
176 help="Host where ODL controller is running (default \
182 help="Port on which ODL's RESTCONF is listening \
188 help="Start incrementing EID from this address \
189 (default is 10.0.0.0)",
194 help="Network mask for the IPv4 EID prefixes \
199 default="172.16.0.0",
200 help='Start incrementing RLOC from this address \
201 (default is 172.16.0.0, ignored for "get")',
207 help="Number of mappings to add/get (default 1)",
212 help='OpenDaylight version, can be "Li" or "Be" \
216 in_args = parser.parse_args()
218 mapping_rpc_blaster = MappingRPCBlaster(
228 if in_args.mode == "add":
229 mapping_rpc_blaster.add_n_mappings()
230 elif in_args.mode == "get":
231 mapping_rpc_blaster.get_n_mappings()
233 print("Unsupported mode:", in_args.mode)