345 | | As indicated in the comments, the top portion of the configuration listens ('''!FromDevice''') for IP packets arriving on the interface connected to '''hostA''' (that's '''eth3''' in this example). It then creates a new 16-byte field at the head of the packet (two bytes added by the '''Unstrip''' operation, plus the existing 14-byte Ethernet header. It fills that field with what could be important routing instructions, but in this case is just graffiti ('''!StoreData'''). The '''route''' operation then routes the packet via either the '''left''' or '''right''' router toward '''hostB'''. In either case, it wraps the packet in a fresh Ethernet header ('''!EtherEncap''') with a distinctive ether type code (0x7744), logs the new packet on its way out ('''Print''') and sends it out on the correct interface ('''!ToDevice'''). |
346 | | |
347 | | The bottom portion of the configuration is intended for packets coming out of the core network to '''hostA'''. It accepts packets from either the '''left''' or '''right''' router, logs them, strips off thirty bytes (Ethernet header plus your 16-byte new header field), puts on a fresh Ethernet header, and sends them along to '''hostA'''. |
348 | | |
349 | | The configuration for the '''bottom''' router is exactly symmetric, routing packets between '''hostB''' and the core network, but using different graffiti. |
350 | | |
351 | | === Simple Forwarding === |
352 | | |
353 | | The '''left''' router configuration is much simpler. Here's the '''left.click''' file: |
| 348 | As indicated in the comments, the top portion of the configuration listens ('''!FromDevice''') for IP packets arriving on the interface connected to '''hostA''' (that's '''eth3''' in this example). It then creates a new 16-byte field at the head of the packet (two bytes added by the '''Unstrip''' operation, plus the existing 14-byte Ethernet header. It fills that field with what could be important routing instructions, but in this case is just graffiti ('''!StoreData'''). The '''route''' operation then routes the packet via either the '''left''' or '''right''' router toward '''hostB'''. In either case, it wraps the packet in a fresh Ethernet header ('''!EtherEncap''') with a distinctive ether type code (0x7744), logs the new packet on its way out ('''Print''') and sends it out on the correct interface ('''!ToDevice'''). |
| 349 | |
| 350 | The bottom portion of the configuration is intended for packets coming out of the core network to '''hostA'''. It accepts packets from either the '''left''' or '''right''' router, logs them, strips off thirty bytes (Ethernet header plus your 16-byte new header field), puts on a fresh Ethernet header, and sends them along to '''hostA'''. |
| 351 | |
| 352 | The configuration for the '''bottom''' router is exactly symmetric, routing packets between '''hostB''' and the core network, but using different graffiti. |
| 353 | |
| 354 | === 7b. Simple Forwarding === |
| 355 | |
| 356 | The '''left''' router configuration is much simpler. In a local terminal type: |
| 357 | {{{ |
| 358 | ssh -A left "cat left.click" |
| 359 | }}} |
| 360 | The output will look like : |
374 | | === Monitoring your core network === |
375 | | |
376 | | Let's watch how the packets travel through the network. The terminal windows on your four router hosts show the log output from the '''Print''' statements shown above, one line per packet. |
377 | | |
378 | | Type <enter> a few times in each router window to create a space below the existing log entries, so you can identify new log messages as they appear. |
379 | | |
380 | | Now go to your window for hostA, where your '''nc''' command is still running. Type a message into this window. You should see a log message in three of your four router windows. In this example, you might see: |
381 | | |
382 | | In the '''top''' router log: |
383 | | {{{ |
| 381 | === 8. Monitoring your core network === |
| 382 | |
| 383 | Let's watch how the packets travel through the network. |
| 384 | i. In a local terminal type: |
| 385 | {{{ |
| 386 | ssh -A top "tail -f /tmp/click.log" |
| 387 | }}} |
| 388 | i. Go to your window for hostA, where your '''nc''' command is still running. Type a message into this window. You should see a log message in three of your four router windows. In this example, you might see: |
| 389 | i. In the local terminal you will see: |
| 390 | {{{ |
387 | | This log entry says that the '''top''' router received a packet from '''hostA''', modified it, and sent it out to the '''right''' router. If the entry started with '''outL''', that would indicate that it sent the packet out to the '''left''' router. Let's look a bit at the start of the packet (the first 24 bytes are logged). It starts with an Ethernet header. The first six bytes are the MAC address of the destination interface, that's 00:04:23:B7:19:2E, the MAC address of '''eth4''' on '''right'''. The next six bytes are the MAC address of the source interface, 00:04:23:B7:1C:E0, or '''eth4''' on '''top'''. Next comes your ether type, 0x7744. The remaining bytes, "416c 69636557 61734865" are the start of the first field in your new protocol, "!AliceWasHe" in ASCII. |
388 | | |
389 | | Since this packet was routed to the right, there's an entry in the '''right''' router log. This entry indicates that a packet was received from '''top'''. The logged contents show the packet sent to '''bottom''', with rewritten MAC addresses, corresponding to '''eth5''' on '''bottom''' and '''eth5''' on '''right'''. |
390 | | |
391 | | {{{ |
392 | | top: 76 | 000423b7 42590004 23b7192f 7744416c 69636557 61734865 |
393 | | }}} |
394 | | |
395 | | Finally, here's the entry on '''bottom''': |
396 | | {{{ |
397 | | inR: 76 | 000423b7 42590004 23b7192f 7744416c 69636557 61734865 |
398 | | }}} |
399 | | |
400 | | It shows the same packet received from '''right'''. After logging, the packet is rewritten into IP and sent to '''hostB'''. |
401 | | |
402 | | Try typing a few different lines to hostA. You should see some packets routed to the left and some to the right. The routing decision is based on the '''route :: Classifier(27/01%01,-);''' entry in the '''top''' router configuration. Here, the router is looking at the low-order bit of the checksum on the initial IP packet (now at byte position 27 with the addition of the new sixteen byte field at the start of the header). Packets with odd checksums go to the left; those with even checksums go right. |
403 | | |
404 | | Try typing a few lines to hostB. You should see similar behavior, but starting from '''bottom''' and working up. You'll also see the different value inserted in the new header field. |
405 | | |
406 | | == Clean up == |
| 394 | This log entry says that the '''top''' router received a packet from '''hostA''', modified it, and sent it out to the '''right''' router. If the entry started with '''outL''', that would indicate that it sent the packet out to the '''left''' router. Let's look a bit at the start of the packet (the first 24 bytes are logged). It starts with an Ethernet header. The first six bytes are the MAC address of the destination interface, that's 00:04:23:B7:19:2E, the MAC address of '''eth4''' on '''right'''. The next six bytes are the MAC address of the source interface, 00:04:23:B7:1C:E0, or '''eth4''' on '''top'''. Next comes your ether type, 0x7744. The remaining bytes, "416c 69636557 61734865" are the start of the first field in your new protocol, "!AliceWasHe" in ASCII. |
| 395 | |
| 396 | Try typing a few different lines to hostA. You should see some packets routed to the left and some to the right. The routing decision is based on the '''route :: Classifier(27/01%01,-);''' entry in the '''top''' router configuration. Here, the router is looking at the low-order bit of the checksum on the initial IP packet (now at byte position 27 with the addition of the new sixteen byte field at the start of the header). Packets with odd checksums go to the left; those with even checksums go right. |
| 397 | |
| 398 | == 9. Clean up == |
411 | | omni.py deletesliver -a http://www.emulab.net/protogeni/xmlrpc/am StupidSliceName |
412 | | }}} |
413 | | |
414 | | == Moving forward with your experiment == |
415 | | |
416 | | This sample experiment is just a very simple demonstration of how to run a Click-based routing configuration using ProtoGENI. For a more meaningful experiment, you may want to try some of the variations described below. We'd love to hear what you're doing with Click and GENI, and we're here to help. Please let us know at [mailto:help@geni.net]. |
417 | | |
418 | | === Improved routing === |
419 | | |
420 | | Instead of writing "!AliceWasHere" in your packets, perhaps include some real routing instructions. Modify the Click configurations to route packets accordingly. |
421 | | |
422 | | === Richer topology === |
423 | | |
424 | | Incorporate additional hosts into a core network topology that's more interesting than a simple diamond. |
425 | | |
426 | | === Improved performance with kernel-level Click === |
427 | | |
428 | | The Click router supports kernel-level operation. The principles are the same, but the setup is a bit more involved. To use kernel-level Click, you will probably want first to develop and debug your setup at the user level. Drop us a line at [mailto:help@geni.net] for help setting up Click in kernel mode. |
429 | | |
430 | | === Wide-area routing === |
431 | | |
432 | | Modify your rspec to include some ProtoGENI hosts on the Internet2 backbone or at multiple ProtoGENI sites. Additional information available at http://protogeni.net or [mailto:help@geni.net]. |
| 403 | omni.py deletesliver -a pg-utah <slicename> |
| 404 | }}} |