Changes between Version 1 and Version 2 of JoeSandbox/OpenFlowNATExample/Execute


Ignore:
Timestamp:
08/13/14 18:25:11 (5 years ago)
Author:
zwang@bbn.com
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • JoeSandbox/OpenFlowNATExample/Execute

    v1 v2  
    1 = [wiki:JoeSandbox/PingPongExample Ping-Pong Example] =
     1= [wiki:JoeSandbox/OpenFlowNATExample OpenFlow NAT Example] =
    22{{{
    33#!html
     
    66      <tr>
    77         <td>
    8          <a href="http://groups.geni.net/geni/wiki/JoeSandbox/PingPongExample/DesignSetup"> <img border="0" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/Graphics/design.2.png?format=raw" alt="Hello GENI index"  height="90" title="Hello GENI Web server" />  </a>
     8         <a href="http://groups.geni.net/geni/wiki/JoeSandbox/OpenFlowNATExample/DesignSetup"> <img border="0" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/Graphics/design.2.png?format=raw" alt="Hello GENI index"  height="90" title="Hello GENI Web server" />  </a>
    99       </td>
    1010       <td>
    11          <a href="http://groups.geni.net/geni/wiki/JoeSandbox/PingPongExample/Execute"> <img border="0" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/Graphics/execute_on.2.png?format=raw" alt="Hello GENI index"  height="90" title="Hello GENI Web server" />  </a>
     11         <a href="http://groups.geni.net/geni/wiki/JoeSandbox/OpenFlowNATExample/Execute"> <img border="0" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/Graphics/execute_on.2.png?format=raw" alt="Hello GENI index"  height="90" title="Hello GENI Web server" />  </a>
    1212       </td>
    1313       <td>
    14          <a href="http://groups.geni.net/geni/wiki/JoeSandbox/PingPongExample/Finish"> <img border="0" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/Graphics/finish.2.png?format=raw" alt="Hello GENI index"  height="90" title="Hello GENI Web server" />  </a>
     14         <a href="http://groups.geni.net/geni/wiki/JoeSandbox/OpenFlowNATExample/Finish"> <img border="0" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/Graphics/finish.2.png?format=raw" alt="Hello GENI index"  height="90" title="Hello GENI Web server" />  </a>
    1515       </td>
    1616     </tr>
     
    1818}}}
    1919
    20 = STEPS FOR EXECUTING EXAMPLE = 
     20= STEPS FOR EXECUTING EXAMPLE =
    2121
    22 In this section, we will see how communication is carried out through LGI middleware and how regulation is imposed on it. LGI governs the communication by an explicitly specified policy, called the "interaction law", or simply the '''law'''. For the law that allows arbitrary messages, please see [http://www.moses.rutgers.edu/examples/simple/simple.java1 here], and for the law that specifies the communication protocol, please see [http://www.moses.rutgers.edu/examples/pingpong/Pingpong.java1 here]. You can compare them to have a better understanding while doing the experiment.
     22In this section, we are going to build a router for a private address space that needs one-to-many NAT (IP Masquerade) for some reason (e.g. short on public IP or security) using OpenFlow. As shown in the figure below, hosts `inside1` and `inside2` are inside the LAN, while host `outside` is outside. The LAN has only one public IP — '''128.128.129.1'''. (The external IPs we use, 128.128.128.0/24 and 128.128.129.0/24, are just an example. If your public IP happens to be in this subnet, change them to others.)
    2323
    24 There are two '''actors''' need to talk to each other. In order to enforce the communication protocol, we associate each of them with a LGI '''controller'''. The actors cannot send message to each other unless the message is sent through their controllers. According to the law, the controllers will decide whether a message can be sent or received based on the actor's interaction history.
     24[[Image(openflow-nat.png, 50%, nolink)]] 
     25== 1 Test reachability before starting controller ==
     26=== 1.1 Login to your hosts ===
    2527
    26 == 1 Basic communication ==
    27 === 1.1 Start Controllers ===
    28 a. Log into C1 (the hostname for Controller 1) and C2 in separate windows.
     28To start our experiment we need to ssh all of our hosts. Depending on which tool and OS you are using there is a slightly different process for logging in. If you don't know how to SSH to your reserved hosts take a look in [wiki:HowTo/LoginToNodes this page.] Once you have logged in, follow the rest of the instructions.
    2929
    30 b. On C1, start the controller using this command:
     30=== 1.2 Test reachability ===
     31
     32a. First we start a ping from `inside1` to `inside2`, which should also work since they are inside the same LAN.
    3133{{{
    32 C1:~$ java moses.Controller
     34inside1:~$ ping 192.168.0.3 -c 10
    3335}}}
    3436
    35 You should see output like this:
     37b. Then we start a ping from `outside` to `inside1`, which should timeout as no according routing information in its routing table. You can use `route -n` to verify that.
    3638{{{
    37 Controller starts (use -help option for help)
    38 C1:9000 is sandboxed
    39 Location of the configuration files is:
    40 /tmp/moses/controllerConf
     39outside:~$ ping 192.168.0.2 -c 10
    4140}}}
    4241
    43 c. On C2, start the controller using the same command.
     42c. Similarly, we cannot ping from `insideX` to `outside`.
    4443
    45 === 1.2 Start Actors ===
    46 a. Log into A1 (the hostname for Actor 1) and A2 in separate windows.
     44d. You can also use Netcat(nc) to test reachability of TCP and UDP. The behavior should be the same.
    4745
    48 b. On A1, start the actor using the following commands:
     46== 2 Start controller to enable NAT ==
     47
     48=== 2.1 Inside source ===
     49'''We definitely need a better naming for this one'''
     50
     51You can try to write your own controller to implement NAT. However, we've provided you a functional controller, which is a file called nat.py under /tmp/ryu/ .
     52
     53a. Start the controller on `switch` host:
    4954{{{
    50 A1:~$ cd /tmp/
    51 A1:/tmp$ java SomeAgent C1 9000 simple.java1 a1
     55switch:~$ cd /tmp/ryu/
     56switch:~$ PYTHONPATH=. ./bin/ryu-manager nat.py
     57}}}
     58You should see output similar to following log after the switch is connected to the controller
     59{{{
     60loading app nat.py
     61loading app ryu.controller.dpset
     62loading app ryu.controller.ofp_handler
     63instantiating app ryu.controller.dpset of DPSet
     64instantiating app ryu.controller.ofp_handler of OFPHandler
     65instantiating app nat.py of NAT
     66switch connected <ryu.controller.controller.Datapath object at 0x2185210>
     67}}}
     68which means we ask the switch to forward ARP and Ipv6 packets normally, and only perform NAT for TCP, UDP and ICMP.
     69
     70b. On `outside`, we start a nc server:
     71{{{
     72outside:~$ nc -l 6666
     73}}}
     74and we start a nc client on `inside1` to connect it:
     75{{{
     76inside1:~$ nc 128.128.128.2 6666
    5277}}}
    5378
    54 This indicates you are using actor program '''!SomeAgent''' to communicate with a controller, whose hostname is '''C1''' and port number is '''9000'''. The communication is under the protocol written in LGI law file '''simple.java1''' and the actor is using name '''a1'''.
     79c. Now send message between each other and try the same thing between `outside` and `inside2`.
    5580
    56 You should see output like this:
     81d. On the terminal of `switch`, in which you started your controller, you should see a log similar to:
    5782{{{
    58 > java SomeAgent contrname contrport lawfile agname
    59 > java SomeAgent contrname contrport lawfile agname CApub
    60 > java SomeAgent contrname contrport lawfile agname CApub Mycert Myprivkey
    61 -1
    62 Type exit to quit
     83Created mapping 192.168.0.3 31596 to 128.128.129.1 59997
     84}}}
     85Note that there should be only one log per connection, because the rest of the communication will re-use the mapping.
     86
     87=== 2.2 Outside source ===
     88
     89'''I know you hate this part. I'm just putting it here because this example is too short.'''
     90
     91You may be wondering whether it will behave the same if we use `insideX` hosts to be the nc server. You can try it and the answer is no. That's due to the nature of dynamic NAT.
     92
     93However, it will work if we can access the translation table on the switch.
     94
     95a. Look back into the log we got previously:
     96{{{
     97Created mapping 192.168.0.3 31596 to 128.128.129.1 59997
     98}}}
     99Now we know there is mapping between these two pairs.
     100
     101b. Now we start a nc server on `inside2` (`inside1` if your mapping shows 192.168.0.2) on the according port:
     102{{{
     103inside2:~$ nc -l 31596
    63104}}}
    64105
    65 c. Similarly on A2, start the actor using following commands:
     106c. Then on `outside`, we start a nc client:
    66107{{{
    67 A2:~$ cd /tmp/
    68 A2:/tmp$ java SomeAgent C2 9000 simple.java1 a2
     108outside:~$ nc 128.128.128.1 59997
    69109}}}
    70110
    71 === 1.3 Communication ===
    72 You can now send a message using command:
     111d. `outside` and `inside2` should be able to send messages to each other.
     112
     113e. Common solution of handling outside source is providing some way to manually create mapping in advance. We will leave it as an exercise for you to implement it.
     114
     115== 3 Handle ARP and ICMP ==
     116One of very common mistakes that people make, when writing OF controller, is forgetting to handle ARP and ICMP message and finding their controller does not work as expected.
     117
     118=== 3.1 ARP ===
     119As we mentioned before, we should insert rules into the OF switch that allow ARP packets to go through, probably after the switch is connected.
     120
     121=== 3.2 ICMP ===
     122Handling ARP is trivial as NAT does not involve ARP. However, it's not the case for ICMP. If you only process translation for TCP/UDP, you will find you cannot ping between `outside` and `insideX` while nc is working properly. Handling ICMP is even not as straightforward as for TCP/UDP. Because for ICMP, you cannot get port information to bind with. Our provided solution makes use of ICMP echo identifier. You may come up with different approach involves ICMP sequence number or others.
     123
     124a. On `inside1`, start a ping to `outside`.
    73125{{{
    74 send(msg,dest)
     126inside1:~$ ping 128.128.128.2
    75127}}}
    76128
    77 where ''msg'' is the content of the message you want to send and ''dest'' is the LGI address of the destination. For example, in our case, A2's address is a2@C2, where a2 is the name you chose when connecting to the controller and C2 is the hostname of its controller.
    78 
    79 a. On A1, send a message to A2. For example:
     129b. Do the same thing on `inside2`.
    80130{{{
    81 send(hello,a2@C2)
     131inside2:~$ ping 128.128.128.2
    82132}}}
    83133
    84 b. On A2, you should see:
     134You should see both pinging are working.
     135
     136c. On `outside`, use `tcpdump` to check the packets it receives.
    85137{{{
    86 Received: hello
    87 }}}
    88 
    89 You can continue sending messages with each other. Any message should be sent and delivered.
    90 
    91 == 2 Regulated Communication ==
    92 
    93 Now we want to impose the following protocol over the community:
    94 
    95 We allow the exchange of two types of messages: '''ping''' messages, which might represent such things as a question, or a request; and '''pong''' messages, used as a reply to a previously received ping messages. The ping-pong policy regulates the flow of messages between any two actors a1, a2 as follows: a1 cannot send any pong message to a2 unless a2 has previously sent a ping message to a1; and a1 cannot send a second ping message to a2 unless a2 answers with a pong message to a1 following the initial ping.
    96 
    97 We call a ping message sent by a1(a2) to a2(a1) '''unresolved''', if a1(a2) did not receive a corresponding pong to it.
    98 
    99 === 2.1 Start Actors ===
    100 a. CTRL-C in A1 and A2 windows to stop the agents. Use command below to adopt the new law '''Pingpong.java1'''.
    101 {{{
    102 A1:/tmp$ java SomeAgent C1 9000 Pingpong.java1 a1
     138outside:~$ sudo tcpdump -i eth1
    103139}}}
    104140
    105 b. Similarly, start Actor 2:
    106 {{{
    107 A2:/tmp$ java SomeAgent C2 9000 Pingpong.java1 a2
    108 }}}
     141You should see it's receiving two groups of icmp packets, differentiated by icmp_id.
    109142
    110 === 2.2 Communication ===
    111 a. On A1, send a message that does not start with '''"ping("''' or '''"pong("''' to A2. For example:
    112 {{{
    113 send(hello,a2@C2)
    114 }}}
    115 b. On A2, nothing should be received and displayed, because we only allow the two types of messages. Any other messages will be discarded.
     143d.
     144Note that, again, you cannot start the ping from the outside, similar to TCP/UDP. The common solution is to manually map the ping destination to a specific inside IP in advance. We will leave it as an exercise for you to implement it, as well.
    116145
    117 c. On A1, send a message that starts with '''"ping("''' to A2. For example:
    118 {{{
    119 send(ping(hi),a2@C2)
    120 }}}
    121 d. On A2, you should see:
    122 {{{
    123 Received: ping(hi)
    124 }}}
    125 because it is a legitimate message and A1 does not have an '''unresolved ping''' message sent to A2.
    126146
    127 e. On A1, send another message that starts with '''"ping("''' to A2. For example:
    128 {{{
    129 send(ping(hey),a2@C2)
    130 }}}
    131147
    132 f. On A2, this message should not be received and displayed, because A1 now has an '''unresolved ping''' message sent, therefore this message is discarded.
    133148
    134 g. On A2, send a message that starts with '''"pong("''' to A1. For example:
    135 {{{
    136 send(pong(howdy),a1@C1)
    137 }}}
    138 h. On A1, you should see:
    139 {{{
    140 Received: pong(howdy)
    141 }}}
    142 because there is an '''unresolved ping''' message sent by A1 to A2, therefore this '''pong''' message is legitimate and allowed to be sent.
    143149
    144 i. After A1 receives this '''pong(howdy)''' message, its previous '''ping(hi)''' message is resolved. Therefore A1 can send '''ping''' message to A2 now. But let's not to do that for a moment.
    145150
    146 j. On A2, send another message that starts with '''"pong("''' to A1. For example:
    147 {{{
    148 send(pong(yo),a1@C1)
    149 }}}
    150 k. On A1, nothing should be received and displayed, as there is no '''unresolved ping''' message sent by A1 to A2, therefore this '''pong''' message is discarded.
    151151
    152 You can continue sending messages to test the behavior and compare the law files.
    153152
    154 If you want to explore how this protocol is enforced over the whole community and what other policies can be imposed on communication, please see [http://www.moses.rutgers.edu/ here] and [http://www.cs.rutgers.edu/~minsky/pubs.html here].
    155 
    156 = [wiki:JoeSandbox/PingPongExample/Finish Next: Teardown Experiment] =
     153= [wiki:JoeSandbox/OpenFlowNATExample/Finish Next: Teardown Experiment] =