-
Notifications
You must be signed in to change notification settings - Fork 33
Add DAQClient and basic test to simulate access switch with device coupler #936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
adc8199
Change DHCP mode when assigned vlan is 0 and add a client for DAQ gRPC
anurag6 9edf73d
Debugging changes
anurag6 896204a
Client side basic setup
anurag6 3be6aeb
Merge branch 'daq_client' of github.com:anurag6/daq into daq_client
anurag6 3fa7a09
Remove redundant debug logs
anurag6 adb9b55
Push device_coupler into a container
anurag6 4f6b254
Clean device coupler
anurag6 e0c9b02
DAQ startup script
anurag6 1b392ba
Dynamically generate startup.yaml based on docker br ip
anurag6 7a7c959
Get target for daq request from docker br ip
anurag6 c403a06
Sniff for VLAN packets as well during startup tests
anurag6 5c9d3fa
Simulate access switch outside contianer. Add new br in container con…
anurag6 37fb128
Add native_vlan for SHIM case
anurag6 854fb59
Add VXLAN ACL for device coupler that allows packets to be tagged
anurag6 92cd07b
Unify cleanup and revert startup dhcp dump criteria
anurag6 1840637
Cleanup
anurag6 d886a38
More cleanup
anurag6 4ee29c3
Log clean up
anurag6 2badd08
Rename client
anurag6 f780d7c
Clean up daq client code
anurag6 22e7124
Remove trigger debug log
anurag6 349689f
Parametrize simulate_access_switch
anurag6 a9c1c9b
Parametrize network helper
anurag6 f155205
Add a test script to run the test
anurag6 49b8a05
Test against a golden file
anurag6 683260a
Add test to actions
anurag6 f848cf5
Lint fixes
anurag6 31652a8
Add snap to requirements
anurag6 64e4311
Lint fixes
anurag6 897f67f
Lint fixes
anurag6 812dfc9
Correct FOT breakage
anurag6 62188cc
Merge branch 'master' of github.com:anurag6/daq into daq_client
anurag6 01429be
Review fixes
anurag6 8ae3288
Add new tests to golden file
anurag6 dfeedb6
Merge branch 'master' of https://github.com/faucetsdn/daq into daq_cl…
anurag6 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #!/bin/bash -e | ||
|
|
||
| image_name="device_coupler" | ||
|
|
||
| echo Starting $image_name build... | ||
|
|
||
| docker build . -f docker/modules/Dockerfile.device_coupler -t daqf/$image_name | ||
|
|
||
| echo Done with $image_name build. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #!/bin/bash -e | ||
|
|
||
| ROOT=$(realpath $(dirname $0)/..) | ||
| echo ROOT is $ROOT | ||
|
|
||
| usage () { | ||
| echo " $0 -t <trunk-interface>" 1>&2; | ||
| exit 1 | ||
| } | ||
|
|
||
| while getopts "t:" argch; do | ||
| case "${argch}" in | ||
| t) | ||
| trunk_port=${OPTARG} | ||
| ;; | ||
| *) | ||
| usage | ||
| ;; | ||
| esac | ||
| done | ||
| shift "$((OPTIND-1))" | ||
|
|
||
| if [ -z "${trunk_port}" ]; then | ||
| usage | ||
| fi | ||
|
|
||
| $ROOT/bin/build_device_coupler | ||
| $ROOT/bin/start_device_coupler | ||
|
|
||
| pid=$(docker inspect --format="{{ .State.Pid }}" dev_coupler_box) | ||
| sudo ip link set $trunk_port netns $pid | ||
|
|
||
| docker exec dev_coupler_box ip link set $trunk_port up | ||
| docker exec dev_coupler_box python3 device_coupler/network_helper.py --bridge dev_br0 --trunk-iface $trunk_port |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| #!/bin/bash -e | ||
|
|
||
| ROOT=$(realpath $(dirname $0)/..) | ||
| CONTAINER=dev_coupler_box | ||
| INSTDIR=$ROOT/inst | ||
| IMAGE=daqf/device_coupler | ||
| # TODO: Write log files here | ||
| mkdir -p $INSTDIR/device_coupler | ||
| docker_volumes+="\ | ||
| -v $INSTDIR:/root/inst" | ||
|
|
||
| if docker container inspect $CONTAINER --format '{{ .Name }}' > /dev/null 2>&1; then | ||
| echo -n "Cleansing old container $CONTAINER" | ||
| docker rm -f $CONTAINER | ||
| fi | ||
|
|
||
| cid=$(docker run -d --privileged --name $CONTAINER \ | ||
| $docker_volumes $IMAGE) | ||
|
|
||
| echo Container $CONTAINER started as $cid |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -306,7 +306,9 @@ def _on_session_start(self, request): | |
| assert remote_ip, 'remote request ip not specified' | ||
| device = self._devices.create_if_absent(request.device_mac) | ||
| device.port.flapping_start = None # In case this was set from last disconnect. | ||
| device.dhcp_mode = DhcpMode.EXTERNAL | ||
| # Assigned VLAN set => FOT mode. | ||
| # For device coupler mode, DHCP mode shouldn't be external. | ||
| device.dhcp_mode = DhcpMode.EXTERNAL if request.assigned_vlan else DhcpMode.NORMAL | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's probably worthwhile to leave a comment here.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| device.session_endpoint = request.endpoint | ||
| self._remote_trigger(device, request.device_vlan, request.assigned_vlan) | ||
| self._udmi.discovery(device) | ||
|
|
@@ -517,7 +519,7 @@ def _handle_device_learn(self, target_mac, vid): | |
| self._target_set_trigger(device) | ||
|
|
||
| def _remote_trigger(self, device, device_vlan, assigned_vlan): | ||
| assert device_vlan and assigned_vlan, 'expected both device_ and assigned_ vlans' | ||
| assert device_vlan, 'expected device_vlan' | ||
| device.port.flapping_start = 0 | ||
| device.port.active = True | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| """Module to send gRPC requests to DAQ and manage test sessions""" | ||
|
|
||
| from __future__ import absolute_import | ||
|
|
||
| import grpc | ||
| import threading | ||
| import traceback | ||
|
|
||
| from device_coupler.utils import get_logger | ||
| from device_coupler.ovs_helper import OvsHelper | ||
|
|
||
| from daq.proto.session_server_pb2 import SessionParams, SessionResult | ||
| from daq.proto.session_server_pb2_grpc import SessionServerStub | ||
|
|
||
|
|
||
| DEFAULT_SERVER_ADDRESS = '127.0.0.1' | ||
| CONNECT_TIMEOUT_SEC = 60 | ||
|
|
||
|
|
||
| class DAQClient(): | ||
| """gRPC client to send device result""" | ||
|
|
||
| def __init__(self, target, tunnel_ip, ovs_bridge): | ||
| self._logger = get_logger('daqclient') | ||
| self._logger.info('Using target %s', target) | ||
| self._channel = grpc.insecure_channel(target) | ||
| self._stub = None | ||
| self._mac_sessions = {} | ||
| self._lock = threading.Lock() | ||
| self._tunnel_ip = tunnel_ip | ||
| self._endpoint_handler = OvsHelper() | ||
| self._ovs_bridge = ovs_bridge | ||
| # Assigned VLAN is always set to 0 for non-FOT DAQ Client | ||
| self._assigned_vlan = 0 | ||
|
|
||
| def start(self): | ||
| """Start the client handler""" | ||
| grpc.channel_ready_future(self._channel).result(timeout=CONNECT_TIMEOUT_SEC) | ||
| self._stub = SessionServerStub(self._channel) | ||
|
|
||
| def stop(self): | ||
| """Stop client handler""" | ||
|
|
||
| def _connect(self, mac, vlan): | ||
| self._logger.info('Connecting %s with VLAN %s', mac, vlan) | ||
| session_params = SessionParams() | ||
| session_params.device_mac = mac | ||
| session_params.device_vlan = vlan | ||
| session_params.assigned_vlan = self._assigned_vlan | ||
| session_params.endpoint.ip = self._tunnel_ip or DEFAULT_SERVER_ADDRESS | ||
| session = self._stub.StartSession(session_params) | ||
| thread = threading.Thread(target=lambda: self._run_test_session(mac, session)) | ||
| thread.start() | ||
| self._logger.info('Connection of %s with VLAN %s succeeded', mac, vlan) | ||
| return session | ||
|
|
||
| def disconnect(self, mac): | ||
| with self._lock: | ||
| session = self._mac_sessions.get(mac, {}).get('session') | ||
| if session: | ||
| session.cancel() | ||
| mac_session = self._mac_sessions.pop(mac) | ||
| index = mac_session['index'] | ||
| interface = "vxlan%s" % index | ||
| self._endpoint_handler.remove_vxlan_endpoint(interface, self._ovs_bridge) | ||
| self._logger.info('Session terminated for %s', mac) | ||
| else: | ||
| self._logger.warning('Attempt to disconnect unconnected device %s', mac) | ||
|
|
||
| def _is_session_running(self, mac, progress): | ||
| result = self._process_session_progress(mac, progress) | ||
| return result not in ('PASSED', 'FAILED', 'ERROR') | ||
|
|
||
| def _process_session_progress(self, mac, progress): | ||
| endpoint = progress.endpoint | ||
| result_code = progress.result.code | ||
| assert not (endpoint.ip and result_code), 'both endpoint.ip and result.code defined' | ||
| if result_code: | ||
| result_name = SessionResult.ResultCode.Name(result_code) | ||
| self._logger.info('Device report %s as %s', mac, result_name) | ||
| return result_name | ||
| if endpoint.ip: | ||
| self._logger.info('Device report %s endpoint ip: %s)', | ||
| mac, endpoint.ip) | ||
| # TODO: Change the way indexes work. Check for VXLAN port being sent | ||
| index = endpoint.vni | ||
| device = self._mac_sessions[mac] | ||
| device['index'] = index | ||
| interface = "vxlan%s" % index | ||
| self._endpoint_handler.remove_vxlan_endpoint(interface, self._ovs_bridge) | ||
| self._endpoint_handler.create_vxlan_endpoint(interface, endpoint.ip, index) | ||
| self._endpoint_handler.add_iface_to_bridge( | ||
| self._ovs_bridge, interface, tag=device['device_vlan']) | ||
| return None | ||
|
|
||
| def _run_test_session(self, mac, session): | ||
| try: | ||
| for progress in session: | ||
| if not self._is_session_running(mac, progress): | ||
| break | ||
| self._logger.info('Progress complete for %s', mac) | ||
| except Exception as e: | ||
| self._logger.error('Progress exception: %s', e) | ||
| self._logger.error('Traceback: %s', traceback.format_exc()) | ||
| self.disconnect(mac) | ||
|
|
||
| def _initiate_test_session(self, mac, device_vlan): | ||
| if mac in self._mac_sessions: | ||
| self._logger.info('Test session for %s already exists. Ignoring.', mac) | ||
| return | ||
| self._logger.info('Initiating test session for %s on VLAN %s', mac, device_vlan) | ||
|
|
||
| if device_vlan: | ||
| self._mac_sessions[mac] = {} | ||
| self._mac_sessions[mac]['device_vlan'] = device_vlan | ||
| self._mac_sessions[mac]['session'] = self._connect(mac, device_vlan) | ||
| self._logger.info('Initiated test session %s', self._mac_sessions[mac]) | ||
|
|
||
| def process_device_discovery(self, mac, device_vlan): | ||
| """Process discovery of device to be tested""" | ||
| # TODO: End existing test session and start new one if discovered on another port | ||
| with self._lock: | ||
| self._initiate_test_session(mac, device_vlan) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # DAQ FOT configuration. | ||
|
|
||
| include: ${DAQ_LIB}/config/system/default.yaml | ||
|
|
||
| host_tests: ${DAQ_LIB}/config/modules/dts.conf | ||
|
|
||
| switch_setup: | ||
| lo_port: 6653 | ||
| varz_port: 5678 | ||
|
|
||
| run_trigger: | ||
| vlan_start: 209 | ||
| vlan_end: 211 | ||
|
|
||
| device_reporting: | ||
| server_port: 50051 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| site_description: generated | ||
| switch_setup: | ||
| endpoint: | ||
| ip: 10.0.0.1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| #!/bin/bash -e | ||
|
|
||
| # Start OVS | ||
| sudo /usr/share/openvswitch/scripts/ovs-ctl start | ||
|
|
||
| # Block | ||
| tail -f |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #!/bin/bash -e | ||
|
|
||
| tunnel_ip=$(ip addr show eth0 | fgrep inet | sed -nr 's~.*inet ([0-9.]+)/.*~\1~p') | ||
| grpc_port=50051 | ||
| target=$(echo $tunnel_ip | sed 's:[^.]*$:1:'):$grpc_port | ||
| device_mac="9a:02:57:1e:8f:01" | ||
| device_vlan=210 | ||
| ovs_br="dev_br0" | ||
|
|
||
| python3 device_coupler/test_run.py --target $target --source $tunnel_ip --device_mac $device_mac --device_vlan $device_vlan --ovs_br $ovs_br |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have everything separate from the existing daq images build, testing, logging etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea I am going for is a separate entity that can be integrated easily enough into DAQ. The logging can be merged fairly easily by using daq.utils instead. For now the idea is to get a test_device_coupler running separately like test_shunt that successfully runs the tests in test_aux and gets the same results. The config, logging and testing merging with DAQ is the next step