diff --git a/docs/static/tutorial7/scenario.png b/docs/static/tutorial7/scenario.png new file mode 100644 index 00000000..1c677aa3 Binary files /dev/null and b/docs/static/tutorial7/scenario.png differ diff --git a/docs/tutorials/tutorial7.md b/docs/tutorials/tutorial7.md new file mode 100644 index 00000000..89a84555 --- /dev/null +++ b/docs/tutorials/tutorial7.md @@ -0,0 +1,236 @@ +# Tutorial 7 - EMANE + +## Overview + +This tutorial will cover basic usage and some concepts one may want to +use or leverage when working with and creating EMANE based networks. + +<p align="center"> + <img src="/static/tutorial7/scenario.png" width="75%"> +</p> + +For more detailed information on EMANE see the following: + +* [EMANE in CORE](../emane.md) +* [EMANE Wiki](https://github.com/adjacentlink/emane/wiki) + +## Files + +Below is a list of the files used for this tutorial. + +* 2 node EMANE ieee80211abg scenario + * scenario.xml + * scenario.py +* 2 node EMANE ieee80211abg scenario, with **n2** running the "Chat App Server" service + * scenario_service.xml + * scenario_service.py + +## Running this Tutorial + +This section covers interactions that can be carried out for this scenario. + +Our scenario has the following nodes and addresses: + +* emane1 - no address, this is a representative node for the EMANE network +* n2 - 10.0.0.1 +* n3 - 10.0.0.2 + +All usages below assume a clean scenario start. + +### Using Ping + +Using the command line utility **ping** can be a good way to verify connectivity +between nodes in CORE. + +* Make sure the CORE daemon is running a terminal, if not already + ``` shell + sudop core-daemon + ``` +* In another terminal run the GUI + ``` shell + core-gui + ``` +* In the GUI menu bar select **File->Open...**, then navigate to and select **scenario.xml** + <p align="center"> + <img src="/static/tutorial-common/running-open.png" width="75%"> + </p> +* You can now click on the **Start Session** button to run the scenario + <p align="center"> + <img src="/static/tutorial7/scenario.png" width="75%"> + </p> +* Open a terminal on **n2** by double clicking it in the GUI +* Run the following in **n2** terminal + ``` shell + ping -c 3 10.0.0.2 + ``` +* You should see the following output + ``` shell + PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data. + 64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=7.93 ms + 64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=3.07 ms + 64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=3.05 ms + + --- 10.0.0.2 ping statistics --- + 3 packets transmitted, 3 received, 0% packet loss, time 2000ms + rtt min/avg/max/mdev = 3.049/4.685/7.932/2.295 ms + ``` + +### Using Tcpdump + +Using **tcpdump** can be very beneficial for examining a network. You can verify +traffic being sent/received among many other uses. + +* Make sure the CORE daemon is running a terminal, if not already + ``` shell + sudop core-daemon + ``` +* In another terminal run the GUI + ``` shell + core-gui + ``` +* In the GUI menu bar select **File->Open...**, then navigate to and select **scenario.xml** + <p align="center"> + <img src="/static/tutorial-common/running-open.png" width="75%"> + </p> +* You can now click on the **Start Session** button to run the scenario + <p align="center"> + <img src="/static/tutorial7/scenario.png" width="75%"> + </p> +* Open a terminal on **n2** by double clicking it in the GUI +* Open a terminal on **n3** by double clicking it in the GUI +* Run the following in **n3** terminal + ``` shell + tcpdump -lenni eth0 + ``` +* Run the following in **n2** terminal + ``` shell + ping -c 1 10.0.0.2 + ``` +* You should see the following in **n2** terminal + ``` shell + tcpdump: verbose output suppressed, use -v[v]... for full protocol decode + listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes + 14:56:25.414283 02:02:00:00:00:01 > 02:02:00:00:00:02, ethertype IPv4 (0x0800), length 98: 10.0.0.1 > 10.0.0.2: ICMP echo request, id 64832, seq 1, length 64 + 14:56:25.414303 02:02:00:00:00:02 > 02:02:00:00:00:01, ethertype IPv4 (0x0800), length 98: 10.0.0.2 > 10.0.0.1: ICMP echo reply, id 64832, seq 1, length 64 + ``` + +### Running Software + +We will now leverage the installed Chat App software to stand up a server and client +within the nodes of our scenario. + +* Make sure the CORE daemon is running a terminal, if not already + ``` shell + sudop core-daemon + ``` +* In another terminal run the GUI + ``` shell + core-gui + ``` +* In the GUI menu bar select **File->Open...**, then navigate to and select **scenario.xml** + <p align="center"> + <img src="/static/tutorial-common/running-open.png" width="75%"> + </p> +* You can now click on the **Start Session** button to run the scenario + <p align="center"> + <img src="/static/tutorial7/scenario.png" width="75%"> + </p> +* Open a terminal on **n2** by double clicking it in the GUI +* Run the following in **n2** terminal + ``` shell + export PATH=$PATH:/usr/local/bin + chatapp-server + ``` +* Open a terminal on **n3** by double clicking it in the GUI +* Run the following in **n3** terminal + ``` shell + export PATH=$PATH:/usr/local/bin + chatapp-client -a 10.0.0.1 + ``` +* You will see the following output in **n1** terminal + ``` shell + chat server listening on: :9001 + [server] 10.0.0.1:44362 joining + ``` +* Type the following in **n2** terminal and hit enter + ``` shell + hello world + ``` +* You will see the following output in **n1** terminal + ``` shell + chat server listening on: :9001 + [server] 10.0.0.2:44362 joining + [10.0.0.2:44362] hello world + ``` + +### Tailing a Log + +In this case we are using the service based scenario. This will automatically start +and run the Chat App Server on **n2** and log to a file. This case will demonstrate +using `tail -f` to observe the output of running software. + +* Make sure the CORE daemon is running a terminal, if not already + ``` shell + sudop core-daemon + ``` +* In another terminal run the GUI + ``` shell + core-gui + ``` +* In the GUI menu bar select **File->Open...**, then navigate to and select **scenario_service.xml** + <p align="center"> + <img src="/static/tutorial-common/running-open.png" width="75%"> + </p> +* You can now click on the **Start Session** button to run the scenario + <p align="center"> + <img src="/static/tutorial7/scenario.png" width="75%"> + </p> +* Open a terminal on **n2** by double clicking it in the GUI +* Run the following in **n2** terminal + ``` shell + tail -f chatapp.log + ``` +* Open a terminal on **n3** by double clicking it in the GUI +* Run the following in **n3** terminal + ``` shell + export PATH=$PATH:/usr/local/bin + chatapp-client -a 10.0.0.1 + ``` +* You will see the following output in **n2** terminal + ``` shell + chat server listening on: :9001 + [server] 10.0.0.2:44362 joining + ``` +* Type the following in **n3** terminal and hit enter + ``` shell + hello world + ``` +* You will see the following output in **n2** terminal + ``` shell + chat server listening on: :9001 + [server] 10.0.0.2:44362 joining + [10.0.0.2:44362] hello world + ``` + +## Advanced Topics + +This section will cover some high level topics and examples for running and +using EMANE in CORE. You can find more detailed tutorials and examples at +the [EMANE Tutorial](https://github.com/adjacentlink/emane-tutorial/wiki). + +!!! note + + Every topic below assumes CORE, EMANE, and OSPF MDR have been installed. + + Scenario files to support the EMANE topics below will be found in + the GUI default directory for opening XML files. + +| Topic | Model | Description | +|-----------------------------------------|---------|-----------------------------------------------------------| +| [XML Files](../emane/files.md) | RF Pipe | Overview of generated XML files used to drive EMANE | +| [GPSD](../emane/gpsd.md) | RF Pipe | Overview of running and integrating gpsd with EMANE | +| [Precomputed](../emane/precomputed.md) | RF Pipe | Overview of using the precomputed propagation model | +| [EEL](../emane/eel.md) | RF Pipe | Overview of using the Emulation Event Log (EEL) Generator | +| [Antenna Profiles](../emane/antenna.md) | RF Pipe | Overview of using antenna profiles in EMANE | + +--8<-- "tutorials/common/grpc.md" diff --git a/mkdocs.yml b/mkdocs.yml index 74bfd331..4879e09e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -42,6 +42,7 @@ nav: - Setup: tutorials/setup.md - Tutorial 1: tutorials/tutorial1.md - Tutorial 4: tutorials/tutorial4.md + - Tutorial 7: tutorials/tutorial7.md - Detailed Topics: - GUI: gui.md - Node Types: diff --git a/package/examples/tutorials/tutorial7/scenario.py b/package/examples/tutorials/tutorial7/scenario.py new file mode 100644 index 00000000..6c4125ed --- /dev/null +++ b/package/examples/tutorials/tutorial7/scenario.py @@ -0,0 +1,52 @@ +from core.api.grpc import client +from core.api.grpc.wrappers import Position, Interface, NodeType +from core.emane.models.ieee80211abg import EmaneIeee80211abgModel + + +def main(): + # interface helper + iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64") + + # create grpc client and connect + core = client.CoreGrpcClient() + core.connect() + + # create session + session = core.create_session() + + # create nodes + position = Position(x=375, y=500) + emane_net = session.add_node( + _id=1, + _type=NodeType.EMANE, + name="emane1", + position=position, + emane=EmaneIeee80211abgModel.name + ) + position = Position(x=250, y=250) + node2 = session.add_node(_id=2, model="mdr", name="n2", position=position) + position = Position(x=500, y=250) + node3 = session.add_node(_id=3, model="mdr", name="n3", position=position) + + # create links to emane + node2_iface = iface_helper.create_iface(node_id=node2.id, iface_id=0) + node2_iface.ip4 = "10.0.0.1" + node2_iface.ip4_mask = 32 + node2_iface.ip6 = "2001::1" + node2_iface.ip6_mask = 128 + # emane_iface1 = Interface(id=0) + session.add_link(node1=node2, node2=emane_net, iface1=node2_iface) + node3_iface = iface_helper.create_iface(node_id=node3.id, iface_id=0) + node3_iface.ip4 = "10.0.0.2" + node3_iface.ip4_mask = 32 + node3_iface.ip6 = "2001::2" + node3_iface.ip6_mask = 128 + # emane_iface2 = Interface(id=1) + session.add_link(node1=node3, node2=emane_net, iface1=node3_iface) + + # start session + core.start_session(session=session) + + +if __name__ == "__main__": + main() diff --git a/package/examples/tutorials/tutorial7/scenario.xml b/package/examples/tutorials/tutorial7/scenario.xml new file mode 100644 index 00000000..721a7b8f --- /dev/null +++ b/package/examples/tutorials/tutorial7/scenario.xml @@ -0,0 +1,90 @@ +<?xml version='1.0' encoding='UTF-8'?> +<scenario name="/tmp/tmpmewk97ls"> + <networks> + <network id="1" name="emane1" icon="" canvas="1" model="emane_ieee80211abg" type="EMANE"> + <position x="375.0" y="500.0" /> + </network> + </networks> + <devices> + <device id="2" name="n2" icon="" canvas="1" type="mdr" class="" image=""> + <position x="250.0" y="250.0" /> + <configservices> + <service name="zebra"/> + <service name="OSPFv3MDR"/> + <service name="IPForward"/> + </configservices> + </device> + <device id="3" name="n3" icon="" canvas="1" type="mdr" class="" image=""> + <position x="500.0" y="250.0" /> + <configservices> + <service name="zebra"/> + <service name="OSPFv3MDR"/> + <service name="IPForward"/> + </configservices> + </device> + </devices> + <links> + <link node1="2" node2="1"> + <iface1 nem="1" id="0" name="eth0" mac="02:02:00:00:00:01" ip4="10.0.0.1" ip4_mask="32" ip6="2001::1" ip6_mask="128"/> + </link> + <link node1="3" node2="1"> + <iface1 nem="2" id="0" name="eth0" mac="02:02:00:00:00:02" ip4="10.0.0.2" ip4_mask="32" ip6="2001::2" ip6_mask="128"/> + </link> + </links> + <configservice_configurations> + <service name="zebra" node="2"/> + <service name="OSPFv3MDR" node="2"/> + <service name="IPForward" node="2"/> + <service name="zebra" node="3"/> + <service name="OSPFv3MDR" node="3"/> + <service name="IPForward" node="3"/> + </configservice_configurations> + <session_origin lat="47.579166412353516" lon="-122.13232421875" alt="2.0" scale="150.0"/> + <session_options> + <configuration name="controlnet" value=""/> + <configuration name="controlnet0" value=""/> + <configuration name="controlnet1" value=""/> + <configuration name="controlnet2" value=""/> + <configuration name="controlnet3" value=""/> + <configuration name="controlnet_updown_script" value=""/> + <configuration name="enablerj45" value="1"/> + <configuration name="preservedir" value="0"/> + <configuration name="enablesdt" value="0"/> + <configuration name="sdturl" value="tcp://127.0.0.1:50000/"/> + <configuration name="ovs" value="0"/> + <configuration name="platform_id_start" value="1"/> + <configuration name="nem_id_start" value="1"/> + <configuration name="link_enabled" value="1"/> + <configuration name="loss_threshold" value="30"/> + <configuration name="link_interval" value="1"/> + <configuration name="link_timeout" value="4"/> + <configuration name="mtu" value="0"/> + </session_options> + <session_metadata> + <configuration name="shapes" value="[]"/> + <configuration name="edges" value="[]"/> + <configuration name="hidden" value="[]"/> + <configuration name="canvas" value="{"gridlines": true, "canvases": [{"id": 1, "wallpaper": null, "wallpaper_style": 1, "fit_image": false, "dimensions": [1000, 750]}]}"/> + </session_metadata> + <default_services> + <node type="mdr"> + <service name="zebra"/> + <service name="OSPFv3MDR"/> + <service name="IPForward"/> + </node> + <node type="PC"> + <service name="DefaultRoute"/> + </node> + <node type="prouter"/> + <node type="router"> + <service name="zebra"/> + <service name="OSPFv2"/> + <service name="OSPFv3"/> + <service name="IPForward"/> + </node> + <node type="host"> + <service name="DefaultRoute"/> + <service name="SSH"/> + </node> + </default_services> +</scenario> diff --git a/package/examples/tutorials/tutorial7/scenario_service.py b/package/examples/tutorials/tutorial7/scenario_service.py new file mode 100644 index 00000000..1f8b0f72 --- /dev/null +++ b/package/examples/tutorials/tutorial7/scenario_service.py @@ -0,0 +1,53 @@ +from core.api.grpc import client +from core.api.grpc.wrappers import Position, Interface, NodeType +from core.emane.models.ieee80211abg import EmaneIeee80211abgModel + + +def main(): + # interface helper + iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64") + + # create grpc client and connect + core = client.CoreGrpcClient() + core.connect() + + # create session + session = core.create_session() + + # create nodes + position = Position(x=375, y=500) + emane_net = session.add_node( + _id=1, + _type=NodeType.EMANE, + name="emane1", + position=position, + emane=EmaneIeee80211abgModel.name + ) + position = Position(x=250, y=250) + node2 = session.add_node(_id=2, model="mdr", name="n2", position=position) + node2.config_services.add("ChatApp Server") + position = Position(x=500, y=250) + node3 = session.add_node(_id=3, model="mdr", name="n3", position=position) + + # create links to emane + node2_iface = iface_helper.create_iface(node_id=node2.id, iface_id=0) + node2_iface.ip4 = "10.0.0.1" + node2_iface.ip4_mask = 32 + node2_iface.ip6 = "2001::1" + node2_iface.ip6_mask = 128 + # emane_iface1 = Interface(id=0) + session.add_link(node1=node2, node2=emane_net, iface1=node2_iface) + node3_iface = iface_helper.create_iface(node_id=node3.id, iface_id=0) + node3_iface.ip4 = "10.0.0.2" + node3_iface.ip4_mask = 32 + node3_iface.ip6 = "2001::2" + node3_iface.ip6_mask = 128 + # emane_iface2 = Interface(id=1) + session.add_link(node1=node3, node2=emane_net, iface1=node3_iface) + + # start session + core.start_session(session=session) + + +if __name__ == "__main__": + main() diff --git a/package/examples/tutorials/tutorial7/scenario_service.xml b/package/examples/tutorials/tutorial7/scenario_service.xml new file mode 100644 index 00000000..da2cb8e8 --- /dev/null +++ b/package/examples/tutorials/tutorial7/scenario_service.xml @@ -0,0 +1,91 @@ +<?xml version='1.0' encoding='UTF-8'?> +<scenario name="/tmp/tmpmewk97ls"> + <networks> + <network id="1" name="emane1" icon="" canvas="1" model="emane_ieee80211abg" type="EMANE"> + <position x="375.0" y="500.0" /> + </network> + </networks> + <devices> + <device id="2" name="n2" icon="" canvas="1" type="mdr" class="" image=""> + <position x="250.0" y="250.0" /> + <configservices> + <service name="zebra"/> + <service name="OSPFv3MDR"/> + <service name="IPForward"/> + <service name="ChatApp Server"/> + </configservices> + </device> + <device id="3" name="n3" icon="" canvas="1" type="mdr" class="" image=""> + <position x="500.0" y="250.0" /> + <configservices> + <service name="zebra"/> + <service name="OSPFv3MDR"/> + <service name="IPForward"/> + </configservices> + </device> + </devices> + <links> + <link node1="2" node2="1"> + <iface1 nem="1" id="0" name="eth0" mac="02:02:00:00:00:01" ip4="10.0.0.1" ip4_mask="32" ip6="2001::1" ip6_mask="128"/> + </link> + <link node1="3" node2="1"> + <iface1 nem="2" id="0" name="eth0" mac="02:02:00:00:00:02" ip4="10.0.0.2" ip4_mask="32" ip6="2001::2" ip6_mask="128"/> + </link> + </links> + <configservice_configurations> + <service name="zebra" node="2"/> + <service name="OSPFv3MDR" node="2"/> + <service name="IPForward" node="2"/> + <service name="zebra" node="3"/> + <service name="OSPFv3MDR" node="3"/> + <service name="IPForward" node="3"/> + </configservice_configurations> + <session_origin lat="47.579166412353516" lon="-122.13232421875" alt="2.0" scale="150.0"/> + <session_options> + <configuration name="controlnet" value=""/> + <configuration name="controlnet0" value=""/> + <configuration name="controlnet1" value=""/> + <configuration name="controlnet2" value=""/> + <configuration name="controlnet3" value=""/> + <configuration name="controlnet_updown_script" value=""/> + <configuration name="enablerj45" value="1"/> + <configuration name="preservedir" value="0"/> + <configuration name="enablesdt" value="0"/> + <configuration name="sdturl" value="tcp://127.0.0.1:50000/"/> + <configuration name="ovs" value="0"/> + <configuration name="platform_id_start" value="1"/> + <configuration name="nem_id_start" value="1"/> + <configuration name="link_enabled" value="1"/> + <configuration name="loss_threshold" value="30"/> + <configuration name="link_interval" value="1"/> + <configuration name="link_timeout" value="4"/> + <configuration name="mtu" value="0"/> + </session_options> + <session_metadata> + <configuration name="shapes" value="[]"/> + <configuration name="edges" value="[]"/> + <configuration name="hidden" value="[]"/> + <configuration name="canvas" value="{"gridlines": true, "canvases": [{"id": 1, "wallpaper": null, "wallpaper_style": 1, "fit_image": false, "dimensions": [1000, 750]}]}"/> + </session_metadata> + <default_services> + <node type="mdr"> + <service name="zebra"/> + <service name="OSPFv3MDR"/> + <service name="IPForward"/> + </node> + <node type="PC"> + <service name="DefaultRoute"/> + </node> + <node type="prouter"/> + <node type="router"> + <service name="zebra"/> + <service name="OSPFv2"/> + <service name="OSPFv3"/> + <service name="IPForward"/> + </node> + <node type="host"> + <service name="DefaultRoute"/> + <service name="SSH"/> + </node> + </default_services> +</scenario>