Skip to content

Commit

Permalink
Added the L2VPN service with QinQ. Moved the l3vpn_qinq services to B…
Browse files Browse the repository at this point in the history
…ackup folder
  • Loading branch information
bfinnema committed Jul 11, 2024
1 parent 07439c2 commit 9032ab0
Show file tree
Hide file tree
Showing 148 changed files with 2,565 additions and 49 deletions.
File renamed without changes.
Binary file added backup/l3vpn_qinq_cfs/load-dir/l3vpn_qinq_cfs.fxs
Binary file not shown.
File renamed without changes.
83 changes: 83 additions & 0 deletions backup/l3vpn_qinq_cfs/python/l3vpn_qinq_cfs/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# -*- mode: python; python-indent: 4 -*-
import ncs
from ncs.application import Service
import requests
import socket
import struct

class ServiceCallbacks(Service):

@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')

def cidr_to_netmask(cidr):
network, net_bits = cidr.split('/')
host_bits = 32 - int(net_bits)
netmask = socket.inet_ntoa(struct.pack('!I', (1 << 32) - (1 << host_bits)))
return network, netmask, net_bits

headers = {"Authorization":"Token e657404c0e1f57481ad0a06c293e8fe794e720ac", "Accept": "application/json", "Content-Type": "application/json"}
body = {}

vars = ncs.template.Variables()
template = ncs.template.Template(service)
for endpoint in service.endpoint:
# PE part
# Get an IP address from Netbox for the PE VPN interface
api_url="https://10.101.180.45/api/ipam/prefixes/1/available-ips/"
response=requests.post(api_url, headers=headers, json=body, verify=False)
self.log.info('Netbox response, IP address reservation: ', response.json())
ipv4_cidr = response.json()["address"]
self.log.info('CIDR from Netbox: ', ipv4_cidr)
ipv4_address, ipv4_mask, ipv4_cidr_mask = cidr_to_netmask(ipv4_cidr)
self.log.info('Address: ', ipv4_address)
self.log.info('Net Mask: ', ipv4_mask)
self.log.info('CIDR Mask: ', ipv4_cidr_mask)
vars.add('pe_ipv4_address', ipv4_address)
vars.add('pe_ipv4_mask', ipv4_mask)

# Get an Outer VLAN from Netbox. The VLAN group for outer VLAN's is #2.
api_url="https://10.101.180.45/api/ipam/vlan-groups/2/available-vlans/"
ovlan_name = "L3VPN-Outer-VLAN-"+str(endpoint.pe_device)+"-"+str(endpoint.id)
body = {"name": ovlan_name}
response=requests.post(api_url, headers=headers, json=body, verify=False)
self.log.info('Netbox response, Outer VLAN reservation: ', response.json())
ovlan_id = response.json()["vid"]
self.log.info('VLAN from Netbox: ', ovlan_id)
vars.add('ovlan', ovlan_id)

# Get an Inner VLAN from Netbox. The VLAN group for inner VLAN's is #3.
api_url="https://10.101.180.45/api/ipam/vlan-groups/3/available-vlans/"
ivlan_name = "L3VPN-Inner-VLAN-"+str(endpoint.pe_device)+"-"+str(endpoint.id)
body = {"name": ivlan_name}
response=requests.post(api_url, headers=headers, json=body, verify=False)
self.log.info('Netbox response, Inner VLAN reservation: ', response.json())
ivlan_id = response.json()["vid"]
self.log.info('VLAN from Netbox: ', ivlan_id)
vars.add('ivlan', ivlan_id)

name = "L3VPN-"+str(endpoint.pe_device)+"-"+str(endpoint.id)
vars.add('name', name)
self.log.info('Name: ', name)
vars.add('pe_device', endpoint.pe_device)
vars.add('cpe_interface_address', endpoint.cpe_interface.ipv4_address)
self.log.info('cpe_interface_address: ', endpoint.cpe_interface.ipv4_address)
vars.add('pe_interface_name', endpoint.pe_interface.interface_name)
vars.add('pe_interface_number', endpoint.pe_interface.interface_number)
pe_interface_description = "L3VPN interface to " + str(endpoint.cpe_device) + ", interface " + str(endpoint.cpe_interface.interface_name) + str(endpoint.cpe_interface.interface_number)
vars.add('pe_interface_description', pe_interface_description)
self.log.info('pe_interface_description: ', pe_interface_description)
# vars.add('pe_ipv4_address', endpoint.pe_interface.ipv4_address)
# vars.add('pe_ipv4_mask', endpoint.pe_interface.ipv4_mask)
self.log.info('ipv4_mask: ', ipv4_mask)
template.apply('l3vpn_qinq_pe-template', vars)


class Main(ncs.application.Application):
def setup(self):
self.log.info('Main RUNNING')
self.register_service('l3vpn_qinq_cfs-servicepoint', ServiceCallbacks)

def teardown(self):
self.log.info('Main FINISHED')
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,15 @@ module l3vpn_qinq_cfs {
type inet:ipv4-address;
}

leaf ovlan {
/* leaf ovlan {
tailf:info "Outer VLAN eg 10";
type uint16;
}
leaf ivlan {
tailf:info "Inner VLAN eg 20";
type uint16;
}
} */

container pe_interface {
uses interface_grouping;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<as_number>{/as_number}</as_number>
<remote_as_number>{/customer_as_number}</remote_as_number>
<neighbor_ip_address>{$cpe_interface_address}</neighbor_ip_address>
<ovlan>{/ovlan}</ovlan>
<ivlan>{/ivlan}</ivlan>
<ovlan>{$ovlan}</ovlan>
<ivlan>{$ivlan}</ivlan>
<interface>
<interface_name>{$pe_interface_name}</interface_name>
<interface_number>{$pe_interface_number}</interface_number>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
23 changes: 23 additions & 0 deletions l2vpn_cfs/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
This is a generated Python package, made by:

ncs-make-package --service-skeleton python-and-template \
--component-class main.Main l2vpn_cfs

It contains a dummy YANG model which implements a minimal Service
and an Action that doesn't really do anything useful. They are
there just to get you going.

You will also find two test cases in:

test/internal/lux/service/
test/internal/lux/action/

that you can run if you have the 'lux' testing tool.
Your top Makefile also need to implement some Make targets
as described in the Makefiles of the test cases.
You can also just read the corresponding run.lux tests and
do them manually if you wish.

The 'lux' test tool can be obtained from:

https://github.com/hawk/lux.git
Binary file added l2vpn_cfs/load-dir/l2vpn_cfs.fxs
Binary file not shown.
13 changes: 13 additions & 0 deletions l2vpn_cfs/package-meta-data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<ncs-package xmlns="http://tail-f.com/ns/ncs-packages">
<name>l2vpn_cfs</name>
<package-version>1.0</package-version>
<description>Generated Python package</description>
<ncs-min-version>6.2</ncs-min-version>

<component>
<name>main</name>
<application>
<python-class-name>l2vpn_cfs.main.Main</python-class-name>
</application>
</component>
</ncs-package>
Empty file.
109 changes: 109 additions & 0 deletions l2vpn_cfs/python/l2vpn_cfs/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# -*- mode: python; python-indent: 4 -*-
import ncs
from ncs.application import Service
import requests

class ServiceCallbacks(Service):

@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')

headers = {"Authorization":"Token e657404c0e1f57481ad0a06c293e8fe794e720ac", "Accept": "application/json", "Content-Type": "application/json"}
body = {}

vars = ncs.template.Variables()
template = ncs.template.Template(service)

for endpoint in service.endpoint:

# Get an Outer VLAN from Netbox. The VLAN group for outer VLAN's is #2.
api_url="https://10.101.180.45/api/ipam/vlan-groups/2/available-vlans/"
ovlan_name = "L2VPN-Outer-VLAN-"+str(endpoint.pe_device)+"-"+str(endpoint.id)
body = {"name": ovlan_name}
try:
response=requests.post(api_url, headers=headers, json=body, verify=False)
self.log.info('Netbox response, Outer VLAN reservation: ', response.json())
ovlan_id = response.json()["vid"]
self.log.info('VLAN from Netbox: ', ovlan_id)
except:
if endpoint.ovlan:
ovlan_id = endpoint.ovlan
else:
ovlan_id = 254
self.log.info('Connection to Netbox failed. Statically allocated Outer VLAN: ', ovlan_id)
vars.add('ovlan', ovlan_id)

# Get an Inner VLAN from Netbox. The VLAN group for inner VLAN's is #3.
api_url="https://10.101.180.45/api/ipam/vlan-groups/3/available-vlans/"
ivlan_name = "L2VPN-Inner-VLAN-"+str(endpoint.pe_device)+"-"+str(endpoint.id)
body = {"name": ivlan_name}
try:
response=requests.post(api_url, headers=headers, json=body, verify=False)
self.log.info('Netbox response, Inner VLAN reservation: ', response.json())
ivlan_id = response.json()["vid"]
self.log.info('VLAN from Netbox: ', ivlan_id)
except:
if endpoint.ivlan:
ivlan_id = endpoint.ivlan
else:
ivlan_id = 253
self.log.info('Connection to Netbox failed. Statically allocated Inner VLAN: ', ivlan_id)
vars.add('ivlan', ivlan_id)

# PE part
name = "L2VPN-"+str(endpoint.pe_device)+"-"+str(endpoint.id)
vars.add('name', name)
self.log.info('Name for PE instance: ', name)
vars.add('pe_device', endpoint.pe_device)
vars.add('bridge_group_name', str(endpoint.id))
# PE to Switch interface configuration:
vars.add('pe_interface_name', endpoint.pe_interface.interface_name)
vars.add('pe_interface_number', endpoint.pe_interface.interface_number)
pe_interface_description = "L2VPN interface to " + str(endpoint.sw_device) + ", interface " + str(endpoint.sw_pe_interface.interface_name) + str(endpoint.sw_pe_interface.interface_number)
vars.add('pe_interface_description', pe_interface_description)
self.log.info('pe_interface_description: ', pe_interface_description)
template.apply('l2vpn_pe-template', vars)

# Switch part
name = "L2VPN-"+str(endpoint.sw_device)+"-"+str(endpoint.id)
vars.add('name', name)
self.log.info('Name for Switch instance: ', name)
vars.add('sw_device', endpoint.sw_device)
vars.add('vlan_name', str(endpoint.id))
# Switch to PE interface configuration:
vars.add('sw_pe_interface_name', endpoint.sw_pe_interface.interface_name)
vars.add('sw_pe_interface_number', endpoint.sw_pe_interface.interface_number)
sw_pe_interface_description = "L2VPN interface to " + str(endpoint.pe_device) + ", interface " + str(endpoint.pe_interface.interface_name) + str(endpoint.pe_interface.interface_number)
vars.add('sw_pe_interface_description', sw_pe_interface_description)
self.log.info('sw_pe_interface_description: ', sw_pe_interface_description)
# Switch to CPE interface configuration:
vars.add('sw_cpe_interface_name', endpoint.sw_cpe_interface.interface_name)
vars.add('sw_cpe_interface_number', endpoint.sw_cpe_interface.interface_number)
sw_cpe_interface_description = "L2VPN interface to " + str(endpoint.cpe_device) + ", interface " + str(endpoint.cpe_interface.interface_name) + str(endpoint.cpe_interface.interface_number)
vars.add('sw_cpe_interface_description', sw_cpe_interface_description)
self.log.info('sw_cpe_interface_description: ', sw_cpe_interface_description)
template.apply('l2vpn_sw-template', vars)

# CPE part
name = "L2VPN-"+str(endpoint.cpe_device)+"-"+str(endpoint.id)
vars.add('name', name)
self.log.info('Name for CPE instance: ', name)
vars.add('cpe_device', endpoint.cpe_device)
vars.add('vlan_name', str(endpoint.id))
# CPE to Switch interface configuration:
vars.add('cpe_interface_name', endpoint.cpe_interface.interface_name)
vars.add('cpe_interface_number', endpoint.cpe_interface.interface_number)
cpe_interface_description = "L2VPN interface to " + str(endpoint.sw_device) + ", interface " + str(endpoint.sw_cpe_interface.interface_name) + str(endpoint.sw_cpe_interface.interface_number)
vars.add('cpe_interface_description', cpe_interface_description)
self.log.info('cpe_interface_description: ', cpe_interface_description)
template.apply('l2vpn_cpe-template', vars)


class Main(ncs.application.Application):
def setup(self):
self.log.info('Main RUNNING')
self.register_service('l2vpn_cfs-servicepoint', ServiceCallbacks)

def teardown(self):
self.log.info('Main FINISHED')
32 changes: 32 additions & 0 deletions l2vpn_cfs/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
all: fxs
.PHONY: all

# Include standard NCS examples build definitions and rules
include $(NCS_DIR)/src/ncs/build/include.ncs.mk

SRC = $(wildcard yang/*.yang)
DIRS = ../load-dir
FXS = $(SRC:yang/%.yang=../load-dir/%.fxs)

## Uncomment and patch the line below if you have a dependency to a NED
## or to other YANG files
# YANGPATH += ../../<ned-name>/src/ncsc-out/modules/yang \
# ../../<pkt-name>/src/yang

NCSCPATH = $(YANGPATH:%=--yangpath %)
YANGERPATH = $(YANGPATH:%=--path %)

fxs: $(DIRS) $(FXS)

$(DIRS):
mkdir -p $@

../load-dir/%.fxs: yang/%.yang
$(NCSC) `ls $*-ann.yang > /dev/null 2>&1 && echo "-a $*-ann.yang"` \
--fail-on-warnings \
$(NCSCPATH) \
-c -o $@ $<

clean:
rm -rf $(DIRS)
.PHONY: clean
Loading

0 comments on commit 9032ab0

Please sign in to comment.