实验参考:
Mininet动态改变转发规则实验
SDN常用控制器安装部署之POX篇
实验步骤:
1. 在装有POX的虚拟机里,/root/pox目录下新建文件lab_controller.py,并编辑以下内容:
1 from pox.core import core 2 3 import pox.openflow.libopenflow_01 as of 4 5 from pox.lib.util import dpidToStr 6 7 from pox.lib.addresses import IPAddr, EthAddr 8 9 from pox.lib.packet.arp import arp 10 11 from pox.lib.packet.ethernet import ethernet, ETHER_BROADCAST 12 13 from pox.lib.packet.packet_base import packet_base 14 15 from pox.lib.packet.packet_utils import * 16 17 import pox.lib.packet as pkt 18 19 from pox.lib.recoco import Timer 20 21 import time 22 23 24 25 log = core.getLogger() 26 27 28 29 s1_dpid=0 30 31 s2_dpid=0 32 33 s3_dpid=0 34 35 s4_dpid=0 36 37 s5_dpid=0 38 39 40 41 s1_p1=0 42 43 s1_p4=0 44 45 s1_p5=0 46 47 s1_p6=0 48 49 s2_p1=0 50 51 s3_p1=0 52 53 s4_p1=0 54 55 56 57 pre_s1_p1=0 58 59 pre_s1_p4=0 60 61 pre_s1_p5=0 62 63 pre_s1_p6=0 64 65 pre_s2_p1=0 66 67 pre_s3_p1=0 68 69 pre_s4_p1=0 70 71 72 73 turn=0 74 75 76 77 def getTheTime(): #fuction to create a timestamp 78 79 flock = time.localtime() 80 81 then = "[%s-%s-%s" %(str(flock.tm_year),str(flock.tm_mon),str(flock.tm_mday)) 82 83 84 85 if int(flock.tm_hour)<10: 86 87 hrs = "0%s" % (str(flock.tm_hour)) 88 89 else: 90 91 hrs = str(flock.tm_hour) 92 93 if int(flock.tm_min)<10: 94 95 mins = str(flock.tm_min) 96 97 secs = "0%s" % (str(flock.tm_sec)) 98 99 else: 100 101 secs = str(flock.tm_sec) 102 103 104 105 then +="]%s.%s.%s" % (hrs,mins,secs) 106 107 return then 108 109 110 111 112 113 def _timer_func (): 114 115 global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid,turn 116 117 118 119 120 121 #print getTheTime(), "sent the port stats request to s1_dpid" 122 123 124 125 if turn==0: 126 127 msg = of.ofp_flow_mod() 128 129 msg.command=of.OFPFC_MODIFY_STRICT 130 131 msg.priority =100 132 133 msg.idle_timeout = 0 134 135 msg.hard_timeout = 0 136 137 msg.match.dl_type = 0x0800 138 139 msg.match.nw_dst = "10.0.0.4" 140 141 msg.actions.append(of.ofp_action_output(port = 5)) 142 143 core.openflow.getConnection(s1_dpid).send(msg) 144 145 turn=1 146 147 return 148 149 150 151 if turn==1: 152 153 msg = of.ofp_flow_mod() 154 155 msg.command=of.OFPFC_MODIFY_STRICT 156 157 msg.priority =100 158 159 msg.idle_timeout = 0 160 161 msg.hard_timeout = 0 162 163 msg.match.dl_type = 0x0800 164 165 msg.match.nw_dst = "10.0.0.4" 166 167 msg.actions.append(of.ofp_action_output(port = 6)) 168 169 core.openflow.getConnection(s1_dpid).send(msg) 170 171 turn=2 172 173 return 174 175 176 177 if turn==2: 178 179 msg = of.ofp_flow_mod() 180 181 msg.command=of.OFPFC_MODIFY_STRICT 182 183 msg.priority =100 184 185 msg.idle_timeout = 0 186 187 msg.hard_timeout = 0 188 189 msg.match.dl_type = 0x0800 190 191 msg.match.nw_dst = "10.0.0.4" 192 193 msg.actions.append(of.ofp_action_output(port = 4)) 194 195 turn=0 196 197 return 198 199 200 201 def _handle_portstats_received (event): 202 203 global s1_p1,s1_p4, s1_p5, s1_p6, s2_p1, s3_p1, s4_p1 204 205 global pre_s1_p1,pre_s1_p4, pre_s1_p5, pre_s1_p6, pre_s2_p1, pre_s3_p1, pre_s4_p1 206 207 208 209 if event.connection.dpid==s1_dpid: 210 211 for f in event.stats: 212 213 if int(f.port_no)<65534: 214 215 if f.port_no==1: 216 217 pre_s1_p1=s1_p1 218 219 s1_p1=f.rx_packets 220 221 222 if f.port_no==4: 223 224 pre_s1_p4=s1_p4 225 226 s1_p4=f.tx_packets 227 228 #s1_p4=f.tx_bytes 229 230 231 if f.port_no==5: 232 233 pre_s1_p5=s1_p5 234 235 s1_p5=f.tx_packets 236 237 if f.port_no==6: 238 239 pre_s1_p6=s1_p6 240 241 s1_p6=f.tx_packets 242 243 244 245 for f in event.stats: 246 247 if int(f.port_no)<65534: 248 249 if f.port_no==1: 250 251 pre_s2_p1=s2_p1 252 253 s2_p1=f.rx_packets 254 255 #s2_p1=f.rx_bytes 256 257 258 if event.connection.dpid==s3_dpid: 259 260 for f in event.stats: 261 262 if int(f.port_no)<65534: 263 264 if f.port_no==1: 265 266 pre_s3_p1=s3_p1 267 268 s3_p1=f.rx_packets 269 270 271 272 273 if event.connection.dpid==s4_dpid: 274 275 for f in event.stats: 276 277 if int(f.port_no)<65534: 278 279 if f.port_no==1: 280 281 pre_s4_p1=s4_p1 282 283 s4_p1=f.rx_packets 284 285 286 287 288 def _handle_ConnectionUp (event): 289 290 global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid 291 292 print "ConnectionUp: ",dpidToStr(event.connection.dpid) 293 294 295 296 #remember the connection dpid for switch 297 298 for m in event.connection.features.ports: 299 300 if m.name == "s1-eth1": 301 302 s1_dpid = event.connection.dpid 303 304 print "s1_dpid=", s1_dpid 305 306 elif m.name == "s2-eth1": 307 308 s2_dpid = event.connection.dpid 309 310 print "s2_dpid=", s2_dpid 311 312 elif m.name == "s3-eth1": 313 314 s3_dpid = event.connection.dpid 315 316 elif m.name == "s4-eth1": 317 318 s4_dpid = event.connection.dpid 319 320 print "s4_dpid=", s4_dpid 321 322 elif m.name == "s5-eth1": 323 324 s5_dpid = event.connection.dpid 325 326 print "s5_dpid=", s5_dpid 327 328 329 330 if s1_dpid<>0 and s2_dpid<>0 and s3_dpid<>0 and s4_dpid<>0: 331 332 Timer(1, _timer_func, recurring=True) 333 334 335 336 def _handle_PacketIn(event): 337 338 global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid 339 340 341 342 packet=event.parsed 343 344 345 346 347 if event.connection.dpid==s1_dpid: 348 349 a=packet.find('arp') 350 351 if a and a.protodst=="10.0.0.4": 352 353 msg = of.ofp_packet_out(data=event.ofp) 354 355 msg.actions.append(of.ofp_action_output(port=4)) 356 357 event.connection.send(msg) 358 359 360 361 if a and a.protodst=="10.0.0.5": 362 363 msg = of.ofp_packet_out(data=event.ofp) 364 365 msg.actions.append(of.ofp_action_output(port=5)) 366 367 event.connection.send(msg) 368 369 370 371 if a and a.protodst=="10.0.0.6": 372 373 msg = of.ofp_packet_out(data=event.ofp) 374 375 msg.actions.append(of.ofp_action_output(port=6)) 376 377 event.connection.send(msg) 378 379 380 381 if a and a.protodst=="10.0.0.1": 382 383 msg = of.ofp_packet_out(data=event.ofp) 384 385 msg.actions.append(of.ofp_action_output(port=1)) 386 387 event.connection.send(msg) 388 389 390 391 if a and a.protodst=="10.0.0.2": 392 393 msg = of.ofp_packet_out(data=event.ofp) 394 395 msg.actions.append(of.ofp_action_output(port=2)) 396 397 event.connection.send(msg) 398 399 400 401 if a and a.protodst=="10.0.0.3": 402 403 msg = of.ofp_packet_out(data=event.ofp) 404 405 msg.actions.append(of.ofp_action_output(port=3)) 406 407 event.connection.send(msg) 408 409 410 411 msg = of.ofp_flow_mod() 412 413 msg.priority =100 414 415 msg.idle_timeout = 0 416 417 msg.hard_timeout = 0 418 419 msg.match.dl_type = 0x0800 420 421 msg.match.nw_dst = "10.0.0.1" 422 423 msg.actions.append(of.ofp_action_output(port = 1)) 424 425 event.connection.send(msg) 426 427 428 429 msg = of.ofp_flow_mod() 430 431 msg.priority =100 432 433 msg.idle_timeout = 0 434 435 msg.hard_timeout = 0 436 437 msg.match.dl_type = 0x0800 438 439 msg.match.nw_dst = "10.0.0.2" 440 441 msg.actions.append(of.ofp_action_output(port = 2)) 442 443 event.connection.send(msg) 444 445 446 447 msg = of.ofp_flow_mod() 448 449 msg.priority =100 450 451 msg.idle_timeout = 0 452 453 msg.hard_timeout = 0 454 455 msg.match.dl_type = 0x0800 456 457 msg.match.nw_dst = "10.0.0.3" 458 459 msg.actions.append(of.ofp_action_output(port = 3)) 460 461 event.connection.send(msg) 462 463 464 465 msg = of.ofp_flow_mod() 466 467 msg.priority =100 468 469 msg.idle_timeout = 0 470 471 msg.hard_timeout = 1 472 473 msg.match.dl_type = 0x0800 474 475 msg.match.nw_dst = "10.0.0.4" 476 477 msg.actions.append(of.ofp_action_output(port = 4)) 478 479 event.connection.send(msg) 480 481 482 483 msg = of.ofp_flow_mod() 484 485 msg.priority =100 486 487 msg.idle_timeout = 0 488 489 msg.hard_timeout = 0 490 491 msg.match.dl_type = 0x0800 492 493 msg.match.nw_dst = "10.0.0.5" 494 495 msg.actions.append(of.ofp_action_output(port = 5)) 496 497 event.connection.send(msg) 498 499 500 501 msg = of.ofp_flow_mod() 502 503 msg.priority =100 504 505 msg.idle_timeout = 0 506 507 msg.hard_timeout = 0 508 509 msg.match.dl_type = 0x0800 510 511 msg.match.nw_dst = "10.0.0.6" 512 513 msg.actions.append(of.ofp_action_output(port = 6)) 514 515 event.connection.send(msg) 516 517 518 519 elif event.connection.dpid==s2_dpid: 520 521 msg = of.ofp_flow_mod() 522 523 msg.priority =10 524 525 msg.idle_timeout = 0 526 527 msg.hard_timeout = 0 528 529 msg.match.in_port = 1 530 531 msg.match.dl_type=0x0806 532 533 msg.actions.append(of.ofp_action_output(port = 2)) 534 535 event.connection.send(msg) 536 537 538 539 msg = of.ofp_flow_mod() 540 541 msg.priority =10 542 543 msg.idle_timeout = 0 544 545 msg.hard_timeout = 0 546 547 msg.match.in_port = 1 548 549 msg.match.dl_type=0x0800 550 551 msg.actions.append(of.ofp_action_output(port = 2)) 552 553 event.connection.send(msg) 554 555 556 557 msg = of.ofp_flow_mod() 558 559 msg.priority =10 560 561 msg.idle_timeout = 0 562 563 msg.hard_timeout = 0 564 565 msg.match.in_port = 2 566 567 msg.match.dl_type=0x0806 568 569 msg.actions.append(of.ofp_action_output(port = 1)) 570 571 event.connection.send(msg) 572 573 574 575 msg = of.ofp_flow_mod() 576 577 msg.priority =10 578 579 msg.idle_timeout = 0 580 581 msg.hard_timeout = 0 582 583 msg.match.in_port = 2 584 585 msg.match.dl_type=0x0800 586 587 msg.actions.append(of.ofp_action_output(port = 1)) 588 589 event.connection.send(msg) 590 591 592 593 elif event.connection.dpid==s3_dpid: 594 595 msg = of.ofp_flow_mod() 596 597 msg.priority =10 598 599 msg.idle_timeout = 0 600 601 msg.hard_timeout = 0 602 603 msg.match.in_port = 1 604 605 msg.match.dl_type=0x0806 606 607 msg.actions.append(of.ofp_action_output(port = 2)) 608 609 event.connection.send(msg) 610 611 612 613 msg = of.ofp_flow_mod() 614 615 msg.priority =10 616 617 msg.idle_timeout = 0 618 619 msg.hard_timeout = 0 620 621 msg.match.in_port = 1 622 623 msg.match.dl_type=0x0800 624 625 msg.actions.append(of.ofp_action_output(port = 2)) 626 627 event.connection.send(msg) 628 629 630 631 msg = of.ofp_flow_mod() 632 633 msg.priority =10 634 635 msg.idle_timeout = 0 636 637 msg.hard_timeout = 0 638 639 msg.match.in_port = 2 640 641 msg.match.dl_type=0x0806 642 643 msg.actions.append(of.ofp_action_output(port = 1)) 644 645 event.connection.send(msg) 646 647 648 649 msg = of.ofp_flow_mod() 650 651 msg.priority =10 652 653 msg.idle_timeout = 0 654 655 msg.hard_timeout = 0 656 657 msg.match.in_port = 2 658 659 msg.match.dl_type=0x0800 660 661 msg.actions.append(of.ofp_action_output(port = 1)) 662 663 event.connection.send(msg) 664 665 666 667 elif event.connection.dpid==s4_dpid: 668 669 msg = of.ofp_flow_mod() 670 671 msg.priority =10 672 673 msg.idle_timeout = 0 674 675 msg.hard_timeout = 0 676 677 msg.match.in_port = 1 678 679 msg.match.dl_type=0x0806 680 681 msg.actions.append(of.ofp_action_output(port = 2)) 682 683 event.connection.send(msg) 684 685 686 687 msg = of.ofp_flow_mod() 688 689 msg.priority =10 690 691 msg.idle_timeout = 0 692 693 msg.hard_timeout = 0 694 695 msg.match.in_port = 1 696 697 msg.match.dl_type=0x0800 698 699 msg.actions.append(of.ofp_action_output(port = 2)) 700 701 event.connection.send(msg) 702 703 704 705 msg = of.ofp_flow_mod() 706 707 msg.priority =10 708 709 msg.idle_timeout = 0 710 711 msg.hard_timeout = 0 712 713 msg.match.in_port = 2 714 715 msg.match.dl_type=0x0806 716 717 msg.actions.append(of.ofp_action_output(port = 1)) 718 719 event.connection.send(msg) 720 721 722 723 msg = of.ofp_flow_mod() 724 725 msg.priority =10 726 727 msg.idle_timeout = 0 728 729 msg.hard_timeout = 0 730 731 msg.match.in_port = 2 732 733 msg.match.dl_type=0x0800 734 735 msg.actions.append(of.ofp_action_output(port = 1)) 736 737 event.connection.send(msg) 738 739 740 741 elif event.connection.dpid==s5_dpid: 742 743 a=packet.find('arp') 744 745 if a and a.protodst=="10.0.0.4": 746 747 msg = of.ofp_packet_out(data=event.ofp) 748 749 msg.actions.append(of.ofp_action_output(port=4)) 750 751 event.connection.send(msg) 752 753 754 755 if a and a.protodst=="10.0.0.5": 756 757 msg = of.ofp_packet_out(data=event.ofp) 758 759 msg.actions.append(of.ofp_action_output(port=5)) 760 761 event.connection.send(msg) 762 763 764 765 if a and a.protodst=="10.0.0.6": 766 767 msg = of.ofp_packet_out(data=event.ofp) 768 769 msg.actions.append(of.ofp_action_output(port=6)) 770 771 event.connection.send(msg) 772 773 774 775 if a and a.protodst=="10.0.0.1": 776 777 msg = of.ofp_packet_out(data=event.ofp) 778 779 msg.actions.append(of.ofp_action_output(port=1)) 780 781 event.connection.send(msg) 782 783 784 785 if a and a.protodst=="10.0.0.2": 786 787 msg = of.ofp_packet_out(data=event.ofp) 788 789 msg.actions.append(of.ofp_action_output(port=2)) 790 791 event.connection.send(msg) 792 793 794 795 if a and a.protodst=="10.0.0.3": 796 797 msg = of.ofp_packet_out(data=event.ofp) 798 799 msg.actions.append(of.ofp_action_output(port=3)) 800 801 event.connection.send(msg) 802 803 804 805 806 807 808 msg = of.ofp_flow_mod() 809 810 msg.priority =100 811 812 msg.idle_timeout = 0 813 814 msg.hard_timeout = 0 815 816 msg.match.dl_type = 0x0800 817 818 msg.match.nw_dst = "10.0.0.1" 819 820 msg.actions.append(of.ofp_action_output(port = 1)) 821 822 event.connection.send(msg) 823 824 825 826 msg = of.ofp_flow_mod() 827 828 msg.priority =100 829 830 msg.idle_timeout = 0 831 832 msg.hard_timeout = 0 833 834 msg.match.dl_type = 0x0800 835 836 msg.match.nw_dst = "10.0.0.2" 837 838 msg.actions.append(of.ofp_action_output(port = 2)) 839 840 event.connection.send(msg) 841 842 843 844 msg = of.ofp_flow_mod() 845 846 msg.priority =100 847 848 msg.idle_timeout = 0 849 850 msg.hard_timeout = 0 851 852 msg.match.dl_type = 0x0800 853 854 msg.match.nw_dst = "10.0.0.3" 855 856 msg.actions.append(of.ofp_action_output(port = 3)) 857 858 event.connection.send(msg) 859 860 861 862 msg = of.ofp_flow_mod() 863 864 msg.priority =100 865 866 msg.idle_timeout = 0 867 868 msg.hard_timeout = 0 869 870 msg.match.dl_type = 0x0800 871 872 msg.match.nw_dst = "10.0.0.4" 873 874 msg.actions.append(of.ofp_action_output(port = 4)) 875 876 event.connection.send(msg) 877 878 879 880 msg = of.ofp_flow_mod() 881 882 msg.priority =100 883 884 msg.idle_timeout = 0 885 886 msg.hard_timeout = 0 887 888 msg.match.dl_type = 0x0800 889 890 msg.match.nw_dst = "10.0.0.5" 891 892 msg.actions.append(of.ofp_action_output(port = 5)) 893 894 event.connection.send(msg) 895 896 897 898 msg = of.ofp_flow_mod() 899 900 msg.priority =100 901 902 msg.idle_timeout = 0 903 904 msg.hard_timeout = 0 905 906 msg.match.dl_type = 0x0800 907 908 msg.match.nw_dst = "10.0.0.6" 909 910 msg.actions.append(of.ofp_action_output(port = 6)) 911 912 event.connection.send(msg) 913 914 915 916 def launch (): 917 918 global start_time 919 920 core.openflow.addListenerByName("PortStatsReceived",_handle_portstats_received) 921 922 core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp) 923 924 core.openflow.addListenerByName("PacketIn",_handle_PacketIn)
2. 进入Mininet文件夹,在其中创建文件mymininet.py,并编辑以下内容(同之前的实验一样,这里要将控制器修改为pox安装的虚拟机的地址,本次仍为127.0.0.1,代码中96行):
1 #!/usr/bin/python 2 3 4 5 from mininet.topo import Topo 6 7 from mininet.net import Mininet 8 9 from mininet.node import CPULimitedHost 10 11 from mininet.link import TCLink 12 13 from mininet.util import dumpNodeConnections 14 15 from mininet.log import setLogLevel 16 17 from mininet.node import Controller 18 19 from mininet.cli import CLI 20 21 from functools import partial 22 23 from mininet.node import RemoteController 24 25 import os 26 27 28 29 30 31 class MyTopo(Topo): 32 33 "Single switch connected to n hosts." 34 35 def __init__(self): 36 37 Topo.__init__(self) 38 39 s1=self.addSwitch('s1') 40 41 s2=self.addSwitch('s2') 42 43 s3=self.addSwitch('s3') 44 45 s4=self.addSwitch('s4') 46 47 s5=self.addSwitch('s5') 48 49 h1=self.addHost('h1') 50 51 h2=self.addHost('h2') 52 53 h3=self.addHost('h3') 54 55 h4=self.addHost('h4') 56 57 h5=self.addHost('h5') 58 59 h6=self.addHost('h6') 60 61 62 63 self.addLink(h1, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 64 65 self.addLink(h2, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 66 67 self.addLink(h3, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 68 69 self.addLink(s1, s2, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 70 71 self.addLink(s1, s3, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 72 73 self.addLink(s1, s4, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 74 75 self.addLink(s2, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 76 77 self.addLink(s3, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 78 79 self.addLink(s4, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 80 81 self.addLink(s5, h4, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 82 83 self.addLink(s5, h5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 84 85 self.addLink(s5, h6, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 86 87 88 89 def perfTest(): 90 91 "Create network and run simple performance test" 92 93 topo = MyTopo() 94 95 96 net = Mininet(topo=topo, host=CPULimitedHost, link=TCLink, controller=partial(RemoteController, ip='127.0.0.1', port=6633)) 97 98 net.start() 99 100 print "Dumping host connections" 101 102 dumpNodeConnections(net.hosts) 103 104 h1,h2,h3=net.get('h1','h2','h3') 105 106 h4,h5,h6=net.get('h4','h5','h6') 107 108 h1.setMAC("0:0:0:0:0:1") 109 110 h2.setMAC("0:0:0:0:0:2") 111 112 h3.setMAC("0:0:0:0:0:3") 113 114 h4.setMAC("0:0:0:0:0:4") 115 116 h5.setMAC("0:0:0:0:0:5") 117 118 h6.setMAC("0:0:0:0:0:6") 119 120 CLI(net) 121 122 net.stop() 123 124 125 126 if __name__ == '__main__': 127 128 setLogLevel('info') 129 130 perfTest()
3. 在POX中,/root/pox目录下运行脚本lab_controller.py。
4. 在Mininet下运行脚本mymininet.py:
5. 查看POX界面,打印出以下内容:
6. 在Mininet中执行h1 ping -i 0.1 h4,每秒从h1传送10个包到h4:
7. 此时查看POX打印出来的结果应该显示循环调度,但我这里的毫无动静,根据评论区的评论,怀疑是,最后选择用poxdesk(安装方法在实验参考的文章里)来查看运行情况。安装完毕后,在浏览器中输入http://pox-ip:8000/poxdesk(这里pox-ip是pox所在的ip,如果本地就直接使用127.0.0.1就行)。登陆后,在左下角的方框中选择TableViwer,之后可以选择s1进行流表项查看:
可以看到,h1无法与h4ping通,除此之外,h2与h5也无法ping通h4,这与预期不符,怀疑是代码问题,但如何修改就在我能力范围之外了
实验结论:
基于Mininet,通过编写POX的脚本内容,可以实现动态改变交换机的转发规则的功能。过程有一些曲折,最后的结果也差强人意,希望在之后的学习中能处理掉这个问题。