github.com/osrg/gobgp@v2.0.0+incompatible/test/scenario_test/global_policy_test.py (about) 1 # Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 # implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 from __future__ import absolute_import 17 18 import sys 19 import time 20 import unittest 21 22 from fabric.api import local 23 import nose 24 25 from lib.noseplugin import OptionParser, parser_option 26 27 from lib import base 28 from lib.base import ( 29 BGP_FSM_IDLE, 30 BGP_FSM_ESTABLISHED, 31 BGP_ATTR_TYPE_COMMUNITIES, 32 ) 33 from lib.gobgp import GoBGPContainer 34 from lib.exabgp import ExaBGPContainer 35 36 37 def community_exists(path, com): 38 a, b = com.split(':') 39 com = (int(a) << 16) + int(b) 40 for a in path['attrs']: 41 if a['type'] == BGP_ATTR_TYPE_COMMUNITIES and com in a['communities']: 42 return True 43 return False 44 45 46 class GoBGPTestBase(unittest.TestCase): 47 48 @classmethod 49 def setUpClass(cls): 50 gobgp_ctn_image_name = parser_option.gobgp_image 51 base.TEST_PREFIX = parser_option.test_prefix 52 53 g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1', 54 ctn_image_name=gobgp_ctn_image_name, 55 log_level=parser_option.gobgp_log_level, 56 config_format=parser_option.config_format) 57 q1 = ExaBGPContainer(name='q1', asn=65001, router_id='192.168.0.2') 58 q2 = ExaBGPContainer(name='q2', asn=65002, router_id='192.168.0.3') 59 q3 = ExaBGPContainer(name='q3', asn=65003, router_id='192.168.0.4') 60 61 qs = [q1, q2, q3] 62 ctns = [g1, q1, q2, q3] 63 64 initial_wait_time = max(ctn.run() for ctn in ctns) 65 time.sleep(initial_wait_time) 66 67 g1.local('gobgp global policy export add default reject') 68 69 for q in qs: 70 g1.add_peer(q) 71 q.add_peer(g1) 72 73 # advertise a route from q1, q2, q3 74 for idx, q in enumerate(qs): 75 route = '10.0.{0}.0/24'.format(idx + 1) 76 q.add_route(route) 77 78 cls.gobgp = g1 79 cls.quaggas = {'q1': q1, 'q2': q2, 'q3': q3} 80 81 # test each neighbor state is turned establish 82 def test_01_neighbor_established(self): 83 for q in self.quaggas.itervalues(): 84 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q) 85 86 def test_02_check_adj_rib_out(self): 87 for q in self.quaggas.itervalues(): 88 self.assertEqual(len(self.gobgp.get_adj_rib_out(q)), 0) 89 90 def test_03_add_peer(self): 91 q = ExaBGPContainer(name='q4', asn=65004, router_id='192.168.0.5') 92 time.sleep(q.run()) 93 self.gobgp.add_peer(q) 94 q.add_peer(self.gobgp) 95 q.add_route('10.10.0.0/24') 96 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q) 97 self.quaggas['q4'] = q 98 for q in self.quaggas.itervalues(): 99 self.assertEqual(len(self.gobgp.get_adj_rib_out(q)), 0) 100 101 def test_04_disable_peer(self): 102 q3 = self.quaggas['q3'] 103 self.gobgp.disable_peer(q3) 104 self.gobgp.wait_for(expected_state=BGP_FSM_IDLE, peer=q3) 105 106 for q in self.quaggas.itervalues(): 107 if q.name == 'q3': 108 continue 109 self.assertEqual(len(self.gobgp.get_adj_rib_out(q)), 0) 110 111 def test_05_enable_peer(self): 112 q3 = self.quaggas['q3'] 113 self.gobgp.enable_peer(q3) 114 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q3) 115 116 for q in self.quaggas.itervalues(): 117 self.assertEqual(len(self.gobgp.get_adj_rib_out(q)), 0) 118 119 def test_06_disable_peer2(self): 120 q3 = self.quaggas['q3'] 121 # advertise a route which was also advertised by q1 122 # this route will be best for g1 because q3's router-id is larger 123 # than q1 124 q3.add_route('10.0.1.0/24') 125 time.sleep(3) 126 # then disable q3 127 self.gobgp.disable_peer(q3) 128 self.gobgp.wait_for(expected_state=BGP_FSM_IDLE, peer=q3) 129 130 for q in self.quaggas.itervalues(): 131 if q.name == 'q3': 132 continue 133 self.assertEqual(len(self.gobgp.get_adj_rib_out(q)), 0) 134 135 def test_07_adv_to_one_peer(self): 136 self.gobgp.local('gobgp policy neighbor add ns0 {0}'.format(self.gobgp.peers[self.quaggas['q1']]['neigh_addr'].split('/')[0])) 137 self.gobgp.local('gobgp policy statement add st0') 138 self.gobgp.local('gobgp policy statement st0 add condition neighbor ns0') 139 self.gobgp.local('gobgp policy statement st0 add action accept') 140 self.gobgp.local('gobgp policy add p0 st0') 141 self.gobgp.local('gobgp global policy export add p0 default reject') 142 for q in self.quaggas.itervalues(): 143 self.gobgp.softreset(q, type='out') 144 145 def test_08_check_adj_rib_out(self): 146 for q in self.quaggas.itervalues(): 147 if q.name == 'q3': 148 continue 149 paths = self.gobgp.get_adj_rib_out(q) 150 if q == self.quaggas['q1']: 151 self.assertEqual(len(paths), 2) 152 else: 153 self.assertEqual(len(paths), 0) 154 155 def test_09_change_global_policy(self): 156 self.gobgp.local('gobgp policy statement st0 add action community add 65100:10') 157 self.gobgp.local('gobgp global policy export set p0 default accept') 158 for q in self.quaggas.itervalues(): 159 self.gobgp.softreset(q, type='out') 160 161 def test_10_check_adj_rib_out(self): 162 for q in self.quaggas.itervalues(): 163 if q.name == 'q3': 164 continue 165 paths = self.gobgp.get_adj_rib_out(q) 166 if q != self.quaggas['q3']: 167 self.assertEqual(len(paths), 2) 168 for path in paths: 169 if q == self.quaggas['q1']: 170 self.assertTrue(community_exists(path, '65100:10')) 171 else: 172 self.assertFalse(community_exists(path, '65100:10')) 173 174 def test_11_add_ibgp_peer(self): 175 q = ExaBGPContainer(name='q5', asn=65000, router_id='192.168.0.6') 176 time.sleep(q.run()) 177 self.quaggas['q5'] = q 178 179 self.gobgp.add_peer(q) 180 q.add_peer(self.gobgp) 181 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q) 182 183 def test_12_add_local_pref_policy(self): 184 self.gobgp.local('gobgp policy statement st1 add action accept') 185 self.gobgp.local('gobgp policy statement st1 add action local-pref 300') 186 self.gobgp.local('gobgp policy add p1 st1') 187 self.gobgp.local('gobgp global policy export set p1 default reject') 188 for q in self.quaggas.itervalues(): 189 self.gobgp.softreset(q, type='out') 190 191 def test_13_check_adj_rib_out(self): 192 q1 = self.quaggas['q1'] 193 for path in self.gobgp.get_adj_rib_out(q1): 194 self.assertTrue(path['local-pref'] is None) 195 q5 = self.quaggas['q5'] 196 for path in self.gobgp.get_adj_rib_out(q5): 197 self.assertEqual(path['local-pref'], 300) 198 199 def test_14_route_type_condition_local(self): 200 self.gobgp.local('gobgp policy statement st2 add action accept') 201 self.gobgp.local('gobgp policy statement st2 add condition route-type local') 202 self.gobgp.local('gobgp policy add p2 st2') 203 self.gobgp.local('gobgp global policy export set p2 default reject') 204 for q in self.quaggas.itervalues(): 205 self.gobgp.softreset(q, type='out') 206 207 q1 = self.quaggas['q1'] 208 self.assertEqual(len(self.gobgp.get_adj_rib_out(q1)), 0) 209 210 self.gobgp.add_route('10.20.0.0/24') 211 212 time.sleep(1) 213 214 self.assertEqual(len(self.gobgp.get_adj_rib_out(q1)), 1) 215 self.assertEqual(self.gobgp.get_adj_rib_out(q1)[0]['nlri']['prefix'], u'10.20.0.0/24') 216 217 def test_15_route_type_condition_internal(self): 218 self.gobgp.local('gobgp policy statement st22 add action accept') 219 self.gobgp.local('gobgp policy statement st22 add condition route-type internal') 220 self.gobgp.local('gobgp policy add p2 st22') 221 self.gobgp.local('gobgp policy del p2 st2') 222 for q in self.quaggas.itervalues(): 223 self.gobgp.softreset(q, type='out') 224 225 q1 = self.quaggas['q1'] 226 self.assertEqual(len(self.gobgp.get_adj_rib_out(q1)), 0) 227 228 q5 = self.quaggas['q5'] 229 q5.add_route('10.30.0.0/24') 230 231 time.sleep(1) 232 233 self.assertEqual(len(self.gobgp.get_adj_rib_out(q1)), 1) 234 self.assertEqual(self.gobgp.get_adj_rib_out(q1)[0]['nlri']['prefix'], u'10.30.0.0/24') 235 236 def test_16_route_type_condition_external(self): 237 self.gobgp.local('gobgp policy statement st222 add action accept') 238 self.gobgp.local('gobgp policy statement st222 add condition route-type external') 239 self.gobgp.local('gobgp policy add p2 st222') 240 self.gobgp.local('gobgp policy del p2 st22') 241 for q in self.quaggas.itervalues(): 242 self.gobgp.softreset(q, type='out') 243 244 q1 = self.quaggas['q1'] 245 num1 = len(self.gobgp.get_adj_rib_out(q1)) 246 247 self.gobgp.add_route('10.40.0.0/24') 248 time.sleep(1) 249 num2 = len(self.gobgp.get_adj_rib_out(q1)) 250 self.assertEqual(num1, num2) 251 252 q5 = self.quaggas['q5'] 253 q5.add_route('10.50.0.0/24') 254 time.sleep(1) 255 num3 = len(self.gobgp.get_adj_rib_out(q1)) 256 self.assertEqual(num1, num3) 257 258 q2 = self.quaggas['q2'] 259 q2.add_route('10.60.0.0/24') 260 time.sleep(1) 261 num4 = len(self.gobgp.get_adj_rib_out(q1)) 262 self.assertEqual(num1 + 1, num4) 263 264 def test_17_multi_statement(self): 265 self.gobgp.local('gobgp policy statement st3 add action med set 100') 266 self.gobgp.local('gobgp policy statement st4 add action local-pref 100') 267 self.gobgp.local('gobgp policy add p3 st3 st4') 268 self.gobgp.local('gobgp global policy import set p3 default accept') 269 270 self.gobgp.add_route('10.70.0.0/24') 271 time.sleep(1) 272 rib = self.gobgp.get_global_rib('10.70.0.0/24') 273 self.assertEqual(len(rib), 1) 274 self.assertEqual(len(rib[0]['paths']), 1) 275 path = rib[0]['paths'][0] 276 self.assertEqual(path['med'], 100) 277 self.assertEqual(path['local-pref'], 100) 278 279 def test_18_reject_policy(self): 280 self.gobgp.local('gobgp global policy import set default reject') 281 self.gobgp.local('gobgp neighbor all softresetin') 282 283 time.sleep(1) 284 285 # self-generated routes remain since softresetin doesn't re-evaluate 286 # them 287 for v in self.gobgp.get_global_rib(): 288 for p in v['paths']: 289 self.assertEqual(p['nexthop'], '0.0.0.0') 290 291 292 if __name__ == '__main__': 293 output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) 294 if int(output) is not 0: 295 print "docker not found" 296 sys.exit(1) 297 298 nose.main(argv=sys.argv, addplugins=[OptionParser()], 299 defaultTest=sys.argv[0])