docs: added tutorial 5
This commit is contained in:
parent
9d88eba1f5
commit
0339073868
10 changed files with 347 additions and 1 deletions
BIN
docs/static/tutorial5/VM-network-settings.png
vendored
Normal file
BIN
docs/static/tutorial5/VM-network-settings.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
docs/static/tutorial5/configure-the-rj45.png
vendored
Normal file
BIN
docs/static/tutorial5/configure-the-rj45.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
BIN
docs/static/tutorial5/rj45-connector.png
vendored
Normal file
BIN
docs/static/tutorial5/rj45-connector.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
docs/static/tutorial5/rj45-unassigned.png
vendored
Normal file
BIN
docs/static/tutorial5/rj45-unassigned.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
|
@ -21,7 +21,7 @@ These are the items you should become familiar with for running all the tutorial
|
||||||
* Covers mobility interactions when using a simple 3 node wireless network
|
* Covers mobility interactions when using a simple 3 node wireless network
|
||||||
* [Tutorial 4 - Tests](tutorial4.md)
|
* [Tutorial 4 - Tests](tutorial4.md)
|
||||||
* Covers automating scenarios as tests to validate software
|
* Covers automating scenarios as tests to validate software
|
||||||
* [Tutorial 5 - Access Windows](tutorial5.md)
|
* [Tutorial 5 - RJ45 Node](tutorial5.md)
|
||||||
* Covers using the RJ45 node to connect a Windows OS
|
* Covers using the RJ45 node to connect a Windows OS
|
||||||
* [Tutorial 6 - Improve Visuals](tutorial6.md)
|
* [Tutorial 6 - Improve Visuals](tutorial6.md)
|
||||||
* Covers changing the look of a scenario within the CORE GUI
|
* Covers changing the look of a scenario within the CORE GUI
|
||||||
|
|
166
docs/tutorials/tutorial5.md
Normal file
166
docs/tutorials/tutorial5.md
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
# Tutorial 5 - RJ45 Node
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This tutorial will cover connecting CORE VM to a Windows host machine using a RJ45 node.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
Below is the list of files used for this tutorial.
|
||||||
|
|
||||||
|
* scenario.xml - the scenario with RJ45 unassigned
|
||||||
|
* scenario.py- grpc script to create the RJ45 in simple CORE scenario
|
||||||
|
* client_for_windows.py - chat app client modified for windows
|
||||||
|
|
||||||
|
## Running with the Saved XML File
|
||||||
|
|
||||||
|
This section covers using the saved **scenario.xml** file to get and up and running.
|
||||||
|
|
||||||
|
* Configure the Windows host VM to have a bridged network adapter
|
||||||
|
<p align="center">
|
||||||
|
<img src="/static/tutorial5/VM-network-settings.png" width="80%">
|
||||||
|
</p>
|
||||||
|
* Make sure the **core-daemon** is running in a terminal
|
||||||
|
```shell
|
||||||
|
sudop core-daemon
|
||||||
|
```
|
||||||
|
* In another terminal run the GUI
|
||||||
|
```shell
|
||||||
|
core-gui
|
||||||
|
```
|
||||||
|
* Open the **scenario.xml** with the unassigned RJ45 node
|
||||||
|
<p align="center">
|
||||||
|
<img src="/static/tutorial5/rj45-unassigned.png" width="80%">
|
||||||
|
</p>
|
||||||
|
* Configure the RJ45 node name to use the bridged interface
|
||||||
|
<p align="center">
|
||||||
|
<img src="/static/tutorial5/configure-the-rj45.png" width="80%">
|
||||||
|
</p>
|
||||||
|
* After configuring the RJ45, run the scenario:
|
||||||
|
<p align="center">
|
||||||
|
<img src="/static/tutorial5/rj45-connector.png" width="80%">
|
||||||
|
</p>
|
||||||
|
* Double click node **n1** to open a terminal and add a route to the Windows host
|
||||||
|
```shell
|
||||||
|
ip route add 192.168.0.0/24 via 10.0.0.20
|
||||||
|
```
|
||||||
|
* On the Windows host using Windows command prompt with administrator privilege, add a route that uses the interface connected to the associated interface assigned to the RJ45 node
|
||||||
|
```shell
|
||||||
|
# if enp0s3 is ssigned 192.168.0.6/24
|
||||||
|
route add 10.0.0.0 mask 255.255.255.0 192.168.0.6
|
||||||
|
```
|
||||||
|
* Now you should be able to ping from the Windows host to **n1**
|
||||||
|
```shell
|
||||||
|
C:\WINDOWS\system32>ping 10.0.0.20
|
||||||
|
|
||||||
|
Pinging 10.0.0.20 with 32 bytes of data:
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
|
||||||
|
Ping statistics for 10.0.0.20:
|
||||||
|
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss)
|
||||||
|
Approximate round trip times in milli-seconds:
|
||||||
|
Minimum = 0ms, Maximum = 0ms, Average = 0ms
|
||||||
|
```
|
||||||
|
* After pinging successfully, run the following in the **n1** terminal to start the chatapp server
|
||||||
|
```shell
|
||||||
|
export PATH=$PATH:/usr/local/bin
|
||||||
|
chatapp-server
|
||||||
|
```
|
||||||
|
* On the Windows host, run the **client_for_windows.py**
|
||||||
|
```shell
|
||||||
|
python3 client_for_windows.py -a 10.0.0.20
|
||||||
|
connected to server(10.0.0.20:9001) as client(192.168.0.6:49960)
|
||||||
|
>> .Hello WORLD
|
||||||
|
.Hello WORLD Again
|
||||||
|
.
|
||||||
|
```
|
||||||
|
* Observe output on **n1**
|
||||||
|
```shell
|
||||||
|
chat server listening on: :9001
|
||||||
|
[server] 192.168.0.6:49960 joining
|
||||||
|
[192.168.0.6:49960] Hello WORLD
|
||||||
|
[192.168.0.6:49960] Hello WORLD Again
|
||||||
|
```
|
||||||
|
* When finished, you can stop the CORE scenario and cleanup
|
||||||
|
* On the Windows host remove the added route
|
||||||
|
```shell
|
||||||
|
route delete 10.0.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running with the gRPC Script
|
||||||
|
|
||||||
|
This section covers leveraging the gRPC script to get up and running.
|
||||||
|
|
||||||
|
* Configure the Windows host VM to have a bridged network adapter
|
||||||
|
<p align="center">
|
||||||
|
<img src="/static/tutorial5/VM-network-settings.png" width="80%">
|
||||||
|
</p>
|
||||||
|
* Make sure the **core-daemon** is running in a terminal
|
||||||
|
```shell
|
||||||
|
sudop core-daemon
|
||||||
|
```
|
||||||
|
* In another terminal run the GUI
|
||||||
|
```shell
|
||||||
|
core-gui
|
||||||
|
```
|
||||||
|
* Run the gRPC script in the VM
|
||||||
|
```shell
|
||||||
|
# use the desired interface name, in this case enp0s3
|
||||||
|
/opt/core/venv/bin/python scenario.py enp0s3
|
||||||
|
```
|
||||||
|
* In the **core-gui** connect to the running session that was created
|
||||||
|
<p align="center">
|
||||||
|
<img src="/static/tutorial5/rj45-connector.png" width="80%">
|
||||||
|
</p>
|
||||||
|
* Double click node **n1** to open a terminal and add a route to the Windows host
|
||||||
|
```shell
|
||||||
|
ip route add 192.168.0.0/24 via 10.0.0.20
|
||||||
|
```
|
||||||
|
* On the Windows host using Windows command prompt with administrator privilege, add a route that uses the interface connected to the associated interface assigned to the RJ45 node
|
||||||
|
```shell
|
||||||
|
# if enp0s3 is ssigned 192.168.0.6/24
|
||||||
|
route add 10.0.0.0 mask 255.255.255.0 192.168.0.6
|
||||||
|
```
|
||||||
|
* Now you should be able to ping from the Windows host to **n1**
|
||||||
|
```shell
|
||||||
|
C:\WINDOWS\system32>ping 10.0.0.20
|
||||||
|
|
||||||
|
Pinging 10.0.0.20 with 32 bytes of data:
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
Reply from 10.0.0.20: bytes=32 time<1ms TTL=64
|
||||||
|
|
||||||
|
Ping statistics for 10.0.0.20:
|
||||||
|
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss)
|
||||||
|
Approximate round trip times in milli-seconds:
|
||||||
|
Minimum = 0ms, Maximum = 0ms, Average = 0ms
|
||||||
|
```
|
||||||
|
* After pinging successfully, run the following in the **n1** terminal to start the chatapp server
|
||||||
|
```shell
|
||||||
|
export PATH=$PATH:/usr/local/bin
|
||||||
|
chatapp-server
|
||||||
|
```
|
||||||
|
* On the Windows host, run the **client_for_windows.py**
|
||||||
|
```shell
|
||||||
|
python3 client_for_windows.py -a 10.0.0.20
|
||||||
|
connected to server(10.0.0.20:9001) as client(192.168.0.6:49960)
|
||||||
|
>> .Hello WORLD
|
||||||
|
.Hello WORLD Again
|
||||||
|
.
|
||||||
|
```
|
||||||
|
* Observe output on **n1**
|
||||||
|
```shell
|
||||||
|
chat server listening on: :9001
|
||||||
|
[server] 192.168.0.6:49960 joining
|
||||||
|
[192.168.0.6:49960] Hello WORLD
|
||||||
|
[192.168.0.6:49960] Hello WORLD Again
|
||||||
|
```
|
||||||
|
* When finished, you can stop the CORE scenario and cleanup
|
||||||
|
* On the Windows host remove the added route
|
||||||
|
```shell
|
||||||
|
route delete 10.0.0.0
|
||||||
|
```
|
|
@ -43,6 +43,7 @@ nav:
|
||||||
- Setup: tutorials/setup.md
|
- Setup: tutorials/setup.md
|
||||||
- Tutorial 1: tutorials/tutorial1.md
|
- Tutorial 1: tutorials/tutorial1.md
|
||||||
- Tutorial 4: tutorials/tutorial4.md
|
- Tutorial 4: tutorials/tutorial4.md
|
||||||
|
- Tutorial 5: tutorials/tutorial5.md
|
||||||
- Tutorial 6: tutorials/tutorial6.md
|
- Tutorial 6: tutorials/tutorial6.md
|
||||||
- Tutorial 7: tutorials/tutorial7.md
|
- Tutorial 7: tutorials/tutorial7.md
|
||||||
- Detailed Topics:
|
- Detailed Topics:
|
||||||
|
|
60
package/examples/tutorials/tutorial5/client_for_windows.py
Normal file
60
package/examples/tutorials/tutorial5/client_for_windows.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import argparse
|
||||||
|
import select
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
DEFAULT_PORT: int = 9001
|
||||||
|
READ_SIZE: int = 4096
|
||||||
|
|
||||||
|
|
||||||
|
def prompt():
|
||||||
|
sys.stdout.write(">> ")
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
class ChatClient:
|
||||||
|
def __init__(self, address, port):
|
||||||
|
self.address = address
|
||||||
|
self.port = port
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
server = socket.create_connection((self.address, self.port))
|
||||||
|
sockname = server.getsockname()
|
||||||
|
print(f"connected to server({self.address}:{self.port}) as client({sockname[0]}:{sockname[1]})")
|
||||||
|
sockets = [server]
|
||||||
|
prompt()
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
read_sockets, write_socket, error_socket = select.select(sockets, [], [], 10)
|
||||||
|
for sock in read_sockets:
|
||||||
|
if sock == server:
|
||||||
|
message = server.recv(READ_SIZE)
|
||||||
|
if not message:
|
||||||
|
print("server closed")
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print("\x1b[2K\r", end="")
|
||||||
|
print(message.decode().strip())
|
||||||
|
prompt()
|
||||||
|
# waiting for input
|
||||||
|
message = input(".")
|
||||||
|
server.sendall(f"{message}\n".encode())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("client exiting")
|
||||||
|
server.close()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="chat app client",
|
||||||
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||||
|
)
|
||||||
|
parser.add_argument("-a", "--address", help="address to listen on", required=True)
|
||||||
|
parser.add_argument("-p", "--port", type=int, help="port to listen on", default=DEFAULT_PORT)
|
||||||
|
args = parser.parse_args()
|
||||||
|
client = ChatClient(args.address, args.port)
|
||||||
|
client.run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
40
package/examples/tutorials/tutorial5/scenario.py
Normal file
40
package/examples/tutorials/tutorial5/scenario.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from core.api.grpc import client, wrappers
|
||||||
|
from core.api.grpc.wrappers import NodeType, Position
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if (len(sys.argv) != 2):
|
||||||
|
print("usage core-python scenario.py <interface-name>")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
# add session
|
||||||
|
session = core.create_session()
|
||||||
|
|
||||||
|
# create nodes
|
||||||
|
position = Position(x=100, y=100)
|
||||||
|
node1 = session.add_node(1, name="n1", position=position)
|
||||||
|
position = Position(x=300, y=100)
|
||||||
|
rj45 = session.add_node(2, name=sys.argv[1], _type=NodeType.RJ45, position=position)
|
||||||
|
|
||||||
|
# create link
|
||||||
|
iface1 = iface_helper.create_iface(node1.id, 0)
|
||||||
|
iface1.ip4 = "10.0.0.20"
|
||||||
|
iface1.ip6 = "2001::14"
|
||||||
|
rj45_iface1 = wrappers.Interface(0)
|
||||||
|
session.add_link(node1=node1, node2=rj45, iface1=iface1, iface2=rj45_iface1)
|
||||||
|
|
||||||
|
# start session
|
||||||
|
core.start_session(session)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
79
package/examples/tutorials/tutorial5/scenario.xml
Normal file
79
package/examples/tutorials/tutorial5/scenario.xml
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<scenario name="/tmp/tmp8mbqm1qx">
|
||||||
|
<networks>
|
||||||
|
<network id="2" name="unassigned" icon="" canvas="1" type="RJ45">
|
||||||
|
<position x="235.0" y="255.0" lat="47.5768484978344" lon="-122.12915765737347" alt="2.0"/>
|
||||||
|
</network>
|
||||||
|
</networks>
|
||||||
|
<devices>
|
||||||
|
<device id="1" name="n1" icon="" canvas="1" type="PC" class="" image="">
|
||||||
|
<position x="395.0" y="189.0" lat="47.57744843849355" lon="-122.12700170069158" alt="2.0"/>
|
||||||
|
<configservices>
|
||||||
|
<service name="DefaultRoute"/>
|
||||||
|
</configservices>
|
||||||
|
</device>
|
||||||
|
</devices>
|
||||||
|
<links>
|
||||||
|
<link node1="2" node2="1">
|
||||||
|
<iface1 id="0" name="unassigned"/>
|
||||||
|
<iface2 id="0" name="eth0" ip4="10.0.0.20" ip4_mask="24" ip6="2001::14" ip6_mask="64"/>
|
||||||
|
<options unidirectional="1"/>
|
||||||
|
</link>
|
||||||
|
<link node1="1" node2="2">
|
||||||
|
<iface1 id="0" name="eth0" ip4="10.0.0.20" ip4_mask="24" ip6="2001::14" ip6_mask="64"/>
|
||||||
|
<iface2 id="0" name="unassigned"/>
|
||||||
|
<options delay="0" bandwidth="0" loss="0.0" dup="0" jitter="0" unidirectional="1" buffer="0"/>
|
||||||
|
</link>
|
||||||
|
</links>
|
||||||
|
<configservice_configurations>
|
||||||
|
<service name="DefaultRoute" node="1"/>
|
||||||
|
</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>
|
Loading…
Reference in a new issue