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