]>
Commit | Line | Data |
---|---|---|
4ac1e79f LB |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # Part of NetDEF Topology Tests | |
5 | # | |
6 | # Copyright (c) 2017 by | |
7 | # Network Device Education Foundation, Inc. ("NetDEF") | |
8 | # | |
9 | # Permission to use, copy, modify, and/or distribute this software | |
10 | # for any purpose with or without fee is hereby granted, provided | |
11 | # that the above copyright notice and this permission notice appear | |
12 | # in all copies. | |
13 | # | |
14 | # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |
15 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
17 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
18 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
19 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
20 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
21 | # OF THIS SOFTWARE. | |
22 | # | |
23 | ||
24 | """ | |
25 | customize.py: Simple FRR/Quagga MPLS L3VPN test topology | |
26 | ||
27 | | | |
28 | +----+----+ | |
29 | | ce1 | | |
30 | | 99.0.0.1| CE Router | |
31 | +----+----+ | |
32 | 192.168.1. | .2 ce1-eth0 | |
33 | | .1 r1-eth4 | |
34 | +---------+ | |
35 | | r1 | | |
36 | | 1.1.1.1 | PE Router | |
37 | +----+----+ | |
38 | | .1 r1-eth0 | |
39 | | | |
40 | ~~~~~~~~~~~~~ | |
41 | ~~ sw0 ~~ | |
42 | ~~ 10.0.1.0/24 ~~ | |
43 | ~~~~~~~~~~~~~ | |
44 | |10.0.1.0/24 | |
45 | | | |
46 | | .2 r2-eth0 | |
47 | +----+----+ | |
48 | | r2 | | |
49 | | 2.2.2.2 | P router | |
50 | +--+---+--+ | |
51 | r2-eth2 .2 | | .2 r2-eth1 | |
52 | ______/ \______ | |
53 | / \ | |
54 | ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ | |
55 | ~~ sw2 ~~ ~~ sw1 ~~ | |
56 | ~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~ | |
57 | ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ | |
58 | | / | | |
59 | \ _________/ | | |
60 | \ / \ | |
61 | r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0 | |
62 | +----+--+---+ +----+----+ | |
856b9cce LB |
63 | | r3 | | r4 | r4-eth5 |
64 | | 3.3.3.3 | | 4.4.4.4 |-------+ PE Routers | |
65 | +-----------+ +---------+ | | |
66 | 192.168.1.1 |r3.eth4 192.168.1.1 | r4-eth4 |192.168.2.1 | |
67 | .2 | ceX-eth0 .2 | | .2 | |
68 | +-----+-----+ +----+-----+ +----+-----+ | |
69 | | ce2 | | ce3 | | ce4 | | |
70 | | 99.0.0.2 | | 99.0.0.3 | | 99.0.0.4 | CE Routers | |
71 | +-----+-----+ +----+-----+ +----+-----+ | |
72 | | | | | |
4ac1e79f LB |
73 | |
74 | """ | |
75 | ||
76 | import os | |
77 | import sys | |
78 | import pytest | |
79 | ||
80 | # pylint: disable=C0413 | |
81 | # Import topogen and topotest helpers | |
82 | from lib import topotest | |
83 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
84 | from lib.topolog import logger | |
85 | ||
86 | # Required to instantiate the topology builder class. | |
87 | from mininet.topo import Topo | |
88 | ||
89 | import shutil | |
90 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
91 | # test name based on directory | |
92 | TEST = os.path.basename(CWD) | |
93 | ||
94 | class ThisTestTopo(Topo): | |
95 | "Test topology builder" | |
96 | def build(self, *_args, **_opts): | |
97 | "Build function" | |
98 | tgen = get_topogen(self) | |
99 | ||
100 | # This function only purpose is to define allocation and relationship | |
101 | # between routers, switches and hosts. | |
102 | # | |
103 | # Create P/PE routers | |
104 | for routern in range(1, 5): | |
105 | tgen.add_router('r{}'.format(routern)) | |
106 | # Create CE routers | |
856b9cce | 107 | for routern in range(1, 5): |
4ac1e79f LB |
108 | tgen.add_router('ce{}'.format(routern)) |
109 | ||
110 | #CE/PE links | |
111 | tgen.add_link(tgen.gears['ce1'], tgen.gears['r1'], 'ce1-eth0', 'r1-eth4') | |
112 | tgen.add_link(tgen.gears['ce2'], tgen.gears['r3'], 'ce2-eth0', 'r3-eth4') | |
113 | tgen.add_link(tgen.gears['ce3'], tgen.gears['r4'], 'ce3-eth0', 'r4-eth4') | |
856b9cce | 114 | tgen.add_link(tgen.gears['ce4'], tgen.gears['r4'], 'ce4-eth0', 'r4-eth5') |
4ac1e79f LB |
115 | |
116 | # Create a switch with just one router connected to it to simulate a | |
117 | # empty network. | |
118 | switch = {} | |
119 | switch[0] = tgen.add_switch('sw0') | |
120 | switch[0].add_link(tgen.gears['r1'], nodeif='r1-eth0') | |
121 | switch[0].add_link(tgen.gears['r2'], nodeif='r2-eth0') | |
122 | ||
123 | switch[1] = tgen.add_switch('sw1') | |
124 | switch[1].add_link(tgen.gears['r2'], nodeif='r2-eth1') | |
125 | switch[1].add_link(tgen.gears['r3'], nodeif='r3-eth0') | |
126 | switch[1].add_link(tgen.gears['r4'], nodeif='r4-eth0') | |
127 | ||
128 | switch[1] = tgen.add_switch('sw2') | |
129 | switch[1].add_link(tgen.gears['r2'], nodeif='r2-eth2') | |
130 | switch[1].add_link(tgen.gears['r3'], nodeif='r3-eth1') | |
131 | ||
132 | def doCmd(tgen, rtr, cmd): | |
133 | output = tgen.net[rtr].cmd(cmd).strip() | |
134 | if len(output): | |
135 | logger.info('command output: ' + output) | |
136 | ||
c0ace6d8 | 137 | def ltemplatePreRouterStartHook(): |
4ac1e79f LB |
138 | tgen = get_topogen() |
139 | logger.info('pre router-start hook') | |
140 | #configure r2 mpls interfaces | |
141 | intfs = ['lo', 'r2-eth0', 'r2-eth1', 'r2-eth2'] | |
142 | for intf in intfs: | |
143 | doCmd(tgen, 'r2', 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf)) | |
856b9cce | 144 | #configure cust1 VRFs & MPLS |
4ac1e79f | 145 | rtrs = ['r1', 'r3', 'r4'] |
c0ace6d8 LB |
146 | cmds = ['ip link add cust1 type vrf table 10', |
147 | 'ip ru add oif cust1 table 10', | |
148 | 'ip ru add iif cust1 table 10', | |
149 | 'ip link set dev cust1 up'] | |
4ac1e79f | 150 | for rtr in rtrs: |
2015a497 LB |
151 | if router.has_mpls() == False: |
152 | logger.info('MPLS not supported, test will be skipped') | |
153 | return | |
4ac1e79f LB |
154 | for cmd in cmds: |
155 | doCmd(tgen, rtr, cmd) | |
c0ace6d8 | 156 | doCmd(tgen, rtr, 'ip link set dev {}-eth4 master cust1'.format(rtr)) |
856b9cce | 157 | intfs = ['cust1', 'lo', rtr+'-eth0', rtr+'-eth4'] |
4ac1e79f LB |
158 | for intf in intfs: |
159 | doCmd(tgen, rtr, 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf)) | |
c0ace6d8 | 160 | logger.info('setup {0} vrf cust1, {0}-eth4. enabled mpls input.'.format(rtr)) |
856b9cce LB |
161 | #configure cust2 VRFs & MPLS |
162 | rtrs = ['r4'] | |
163 | cmds = ['ip link add cust2 type vrf table 20', | |
164 | 'ip ru add oif cust1 table 20', | |
165 | 'ip ru add iif cust1 table 20', | |
166 | 'ip link set dev cust2 up'] | |
167 | for rtr in rtrs: | |
168 | for cmd in cmds: | |
169 | doCmd(tgen, rtr, cmd) | |
170 | doCmd(tgen, rtr, 'ip link set dev {}-eth5 master cust2'.format(rtr)) | |
171 | intfs = ['cust2', rtr+'-eth5'] | |
172 | for intf in intfs: | |
173 | doCmd(tgen, rtr, 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf)) | |
174 | logger.info('setup {0} vrf cust2, {0}-eth5. enabled mpls input.'.format(rtr)) | |
4ac1e79f LB |
175 | return; |
176 | ||
c0ace6d8 | 177 | def ltemplatePostRouterStartHook(): |
4ac1e79f LB |
178 | logger.info('post router-start hook') |
179 | return; | |
180 | ||
181 | def versionCheck(vstr, rname='r1', compstr='<',cli=False): | |
182 | tgen = get_topogen() | |
183 | ||
184 | router = tgen.gears[rname] | |
2015a497 LB |
185 | |
186 | if router.has_mpls() == False: | |
187 | ret = 'MPLS not supported' | |
188 | return ret | |
189 | ||
4ac1e79f LB |
190 | ret = True |
191 | try: | |
192 | if router.has_version(compstr, vstr): | |
193 | ret = False | |
194 | logger.debug('version check failed, version {} {}'.format(compstr, vstr)) | |
195 | except: | |
196 | ret = True | |
197 | if ret == False: | |
198 | ret = 'Skipping main tests on old version ({}{})'.format(compstr, vstr) | |
199 | logger.info(ret) | |
200 | if cli: | |
201 | logger.info('calling mininet CLI') | |
202 | tgen.mininet_cli() | |
203 | logger.info('exited mininet CLI') | |
204 | return ret |