Loading src/tests/ryu-openflow/.gitlab-ci.yml +17 −4 Original line number Diff line number Diff line Loading @@ -165,7 +165,7 @@ end2end_test ryu-openflow: # Deploy Mininet # --ulimit memlock=-1:-1 --ulimit nofile=65536:65536 --ulimit nproc=65536:65536 - > docker run --detach --name mininet --network ryu-of-br --ip 172.254.252.11 docker run --detach --name mininet --network ryu-of-br --ip 172.254.252.11 --publish 5000 --privileged --volume /lib/modules:/lib/modules "${CI_REGISTRY_IMAGE}/${TEST_NAME}-mininet:${IMAGE_TAG}" Loading Loading @@ -254,12 +254,25 @@ end2end_test ryu-openflow: - docker exec mininet ovs-ofctl dump-flows s4 - docker exec mininet ovs-ofctl dump-flows s5 # Run end-to-end test: test no connectivity with ping - export TEST_H1_H2=$(curl -s http://172.254.252.10:5000/ping?source=h1&target=h2&count=3) - echo $TEST_H1_H2 - echo $TEST_H1_H2 | grep -E '3 packets transmitted, 0 received, 100\% packet loss' - export TEST_H1_H3=$(curl -s http://172.254.252.10:5000/ping?source=h1&target=h3&count=3) - echo $TEST_H1_H3 - echo $TEST_H1_H3 | grep -E '3 packets transmitted, 0 received, 100\% packet loss' - export TEST_H1_H4=$(curl -s http://172.254.252.10:5000/ping?source=h1&target=h4&count=3) - echo $TEST_H1_H4 - echo $TEST_H1_H4 | grep -E '3 packets transmitted, 0 received, 100\% packet loss' ## Run end-to-end test: configure service IETF #- > # docker run -t --rm --name ${TEST_NAME} --network=host # --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" # --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" # ${CI_REGISTRY_IMAGE}/${TEST_NAME}:${IMAGE_TAG} /var/teraflow/run-service-ietf-create.sh # "${CI_REGISTRY_IMAGE}/${TEST_NAME}-test:${IMAGE_TAG}" /var/teraflow/run-service-ietf-create.sh # Dump configuration of the switches (OpenFlow rules configured) (after configure IETF service) - docker exec mininet bash -c "ovs-vsctl show" Loading Loading @@ -294,7 +307,7 @@ end2end_test ryu-openflow: # docker run -t --rm --name ${TEST_NAME} --network=host # --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" # --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" # ${CI_REGISTRY_IMAGE}/${TEST_NAME}:${IMAGE_TAG} /var/teraflow/run-service-ietf-remove.sh # "${CI_REGISTRY_IMAGE}/${TEST_NAME}-test:${IMAGE_TAG}" /var/teraflow/run-service-ietf-remove.sh # Dump configuration of the switches (OpenFlow rules configured) (after deconfigure IETF service) - docker exec mininet bash -c "ovs-vsctl show" Loading @@ -309,7 +322,7 @@ end2end_test ryu-openflow: docker run -t --rm --name ${TEST_NAME} --network=host --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" ${CI_REGISTRY_IMAGE}/${TEST_NAME}:${IMAGE_TAG} /var/teraflow/run-cleanup.sh "${CI_REGISTRY_IMAGE}/${TEST_NAME}-test:${IMAGE_TAG}" /var/teraflow/run-cleanup.sh after_script: # Dump configuration of the switches (OpenFlow rules configured) (on after_script) Loading src/tests/ryu-openflow/mininet/Mininet.Dockerfile +1 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,6 @@ RUN apt-get --yes --quiet --quiet update && \ COPY src/tests/ryu-openflow/mininet/custom_pentagon_topology.py /opt/custom_pentagon_topology.py COPY src/tests/ryu-openflow/mininet/mininet-entrypoint.sh /mininet-entrypoint.sh EXPOSE 6633 6653 6640 EXPOSE 6633 6653 6640 5000 ENTRYPOINT ["/mininet-entrypoint.sh"] src/tests/ryu-openflow/mininet/custom_pentagon_topology.py +98 −8 Original line number Diff line number Diff line Loading @@ -13,11 +13,13 @@ # limitations under the License. import time import json, re, socketserver, threading, time from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import parse_qs, urlparse from mininet.topo import Topo from mininet.net import Mininet from mininet.node import RemoteController from mininet.cli import CLI #from mininet.cli import CLI from mininet.link import TCLink class PentagonTopo(Topo): Loading @@ -44,6 +46,85 @@ class PentagonTopo(Topo): self.addLink(h3, sw5) self.addLink(h4, sw5) def parse_ping_output(output: str): match = re.search(r'(\d+) packets transmitted, (\d+) received', output) if not match: return 0, 0, 0.0 transmitted = int(match.group(1)) received = int(match.group(2)) ratio = (received / transmitted) if transmitted else 0.0 return transmitted, received, ratio def build_ping_handler(net: Mininet): """ Create a HTTP request handler that performs pings between hosts. """ class PingHandler(BaseHTTPRequestHandler): def log_message(self, *args, **kwargs): # Silence default stdout logging. return def _send_json(self, status: int, payload: dict): body = json.dumps(payload).encode() self.send_response(status) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(body))) self.end_headers() self.wfile.write(body) def do_GET(self): parsed = urlparse(self.path) if parsed.path != '/ping': self._send_json(404, {'error': 'not found'}) return params = parse_qs(parsed.query) source = params.get('source', [None])[0] target = params.get('target', [None])[0] count_val = params.get('count', ['3'])[0] if not source or not target: self._send_json(400, {'error': 'source and target query parameters are required'}) return try: count = int(count_val) if count <= 0: raise ValueError() except ValueError: self._send_json(400, {'error': 'count must be a positive integer'}) return try: src_host = net.get(source) dst_host = net.get(target) except KeyError as exc: self._send_json(404, {'error': f'Unknown host: {exc}'}) return destination_ip = dst_host.IP() output = src_host.cmd(f'ping -c {count} {destination_ip}') transmitted, received, ratio = parse_ping_output(output) self._send_json(200, { 'source': source, 'target': target, 'destination_ip': destination_ip, 'count': count, 'packets_transmitted': transmitted, 'packets_received': received, 'success_ratio': ratio, 'raw_output': output }) return PingHandler class ThreadingHTTPServer(socketserver.ThreadingMixIn, HTTPServer): daemon_threads = True if __name__ == '__main__': topo = PentagonTopo() ctrl = RemoteController('ryu', ip='172.254.252.10', port=6653) Loading @@ -56,10 +137,19 @@ if __name__ == '__main__': net.start() net.staticArp() ping_handler = build_http_handler(net) http_server = ThreadingHTTPServer(('0.0.0.0', 5000), ping_handler) server_thread = threading.Thread(target=http_server.serve_forever, daemon=True) server_thread.start() print('Custom Pentagon Topology is up with static ARP.') #CLI(net) print('HTTP ping server running at http://0.0.0.0:5000/ping?source=h1&target=h2&count=3') try: while True: time.sleep(60) #while True: #time.sleep(60) #net.stop() except KeyboardInterrupt: print('Stopping Mininet...') http_server.shutdown() http_server.server_close() net.stop() Loading
src/tests/ryu-openflow/.gitlab-ci.yml +17 −4 Original line number Diff line number Diff line Loading @@ -165,7 +165,7 @@ end2end_test ryu-openflow: # Deploy Mininet # --ulimit memlock=-1:-1 --ulimit nofile=65536:65536 --ulimit nproc=65536:65536 - > docker run --detach --name mininet --network ryu-of-br --ip 172.254.252.11 docker run --detach --name mininet --network ryu-of-br --ip 172.254.252.11 --publish 5000 --privileged --volume /lib/modules:/lib/modules "${CI_REGISTRY_IMAGE}/${TEST_NAME}-mininet:${IMAGE_TAG}" Loading Loading @@ -254,12 +254,25 @@ end2end_test ryu-openflow: - docker exec mininet ovs-ofctl dump-flows s4 - docker exec mininet ovs-ofctl dump-flows s5 # Run end-to-end test: test no connectivity with ping - export TEST_H1_H2=$(curl -s http://172.254.252.10:5000/ping?source=h1&target=h2&count=3) - echo $TEST_H1_H2 - echo $TEST_H1_H2 | grep -E '3 packets transmitted, 0 received, 100\% packet loss' - export TEST_H1_H3=$(curl -s http://172.254.252.10:5000/ping?source=h1&target=h3&count=3) - echo $TEST_H1_H3 - echo $TEST_H1_H3 | grep -E '3 packets transmitted, 0 received, 100\% packet loss' - export TEST_H1_H4=$(curl -s http://172.254.252.10:5000/ping?source=h1&target=h4&count=3) - echo $TEST_H1_H4 - echo $TEST_H1_H4 | grep -E '3 packets transmitted, 0 received, 100\% packet loss' ## Run end-to-end test: configure service IETF #- > # docker run -t --rm --name ${TEST_NAME} --network=host # --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" # --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" # ${CI_REGISTRY_IMAGE}/${TEST_NAME}:${IMAGE_TAG} /var/teraflow/run-service-ietf-create.sh # "${CI_REGISTRY_IMAGE}/${TEST_NAME}-test:${IMAGE_TAG}" /var/teraflow/run-service-ietf-create.sh # Dump configuration of the switches (OpenFlow rules configured) (after configure IETF service) - docker exec mininet bash -c "ovs-vsctl show" Loading Loading @@ -294,7 +307,7 @@ end2end_test ryu-openflow: # docker run -t --rm --name ${TEST_NAME} --network=host # --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" # --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" # ${CI_REGISTRY_IMAGE}/${TEST_NAME}:${IMAGE_TAG} /var/teraflow/run-service-ietf-remove.sh # "${CI_REGISTRY_IMAGE}/${TEST_NAME}-test:${IMAGE_TAG}" /var/teraflow/run-service-ietf-remove.sh # Dump configuration of the switches (OpenFlow rules configured) (after deconfigure IETF service) - docker exec mininet bash -c "ovs-vsctl show" Loading @@ -309,7 +322,7 @@ end2end_test ryu-openflow: docker run -t --rm --name ${TEST_NAME} --network=host --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" ${CI_REGISTRY_IMAGE}/${TEST_NAME}:${IMAGE_TAG} /var/teraflow/run-cleanup.sh "${CI_REGISTRY_IMAGE}/${TEST_NAME}-test:${IMAGE_TAG}" /var/teraflow/run-cleanup.sh after_script: # Dump configuration of the switches (OpenFlow rules configured) (on after_script) Loading
src/tests/ryu-openflow/mininet/Mininet.Dockerfile +1 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,6 @@ RUN apt-get --yes --quiet --quiet update && \ COPY src/tests/ryu-openflow/mininet/custom_pentagon_topology.py /opt/custom_pentagon_topology.py COPY src/tests/ryu-openflow/mininet/mininet-entrypoint.sh /mininet-entrypoint.sh EXPOSE 6633 6653 6640 EXPOSE 6633 6653 6640 5000 ENTRYPOINT ["/mininet-entrypoint.sh"]
src/tests/ryu-openflow/mininet/custom_pentagon_topology.py +98 −8 Original line number Diff line number Diff line Loading @@ -13,11 +13,13 @@ # limitations under the License. import time import json, re, socketserver, threading, time from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import parse_qs, urlparse from mininet.topo import Topo from mininet.net import Mininet from mininet.node import RemoteController from mininet.cli import CLI #from mininet.cli import CLI from mininet.link import TCLink class PentagonTopo(Topo): Loading @@ -44,6 +46,85 @@ class PentagonTopo(Topo): self.addLink(h3, sw5) self.addLink(h4, sw5) def parse_ping_output(output: str): match = re.search(r'(\d+) packets transmitted, (\d+) received', output) if not match: return 0, 0, 0.0 transmitted = int(match.group(1)) received = int(match.group(2)) ratio = (received / transmitted) if transmitted else 0.0 return transmitted, received, ratio def build_ping_handler(net: Mininet): """ Create a HTTP request handler that performs pings between hosts. """ class PingHandler(BaseHTTPRequestHandler): def log_message(self, *args, **kwargs): # Silence default stdout logging. return def _send_json(self, status: int, payload: dict): body = json.dumps(payload).encode() self.send_response(status) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(body))) self.end_headers() self.wfile.write(body) def do_GET(self): parsed = urlparse(self.path) if parsed.path != '/ping': self._send_json(404, {'error': 'not found'}) return params = parse_qs(parsed.query) source = params.get('source', [None])[0] target = params.get('target', [None])[0] count_val = params.get('count', ['3'])[0] if not source or not target: self._send_json(400, {'error': 'source and target query parameters are required'}) return try: count = int(count_val) if count <= 0: raise ValueError() except ValueError: self._send_json(400, {'error': 'count must be a positive integer'}) return try: src_host = net.get(source) dst_host = net.get(target) except KeyError as exc: self._send_json(404, {'error': f'Unknown host: {exc}'}) return destination_ip = dst_host.IP() output = src_host.cmd(f'ping -c {count} {destination_ip}') transmitted, received, ratio = parse_ping_output(output) self._send_json(200, { 'source': source, 'target': target, 'destination_ip': destination_ip, 'count': count, 'packets_transmitted': transmitted, 'packets_received': received, 'success_ratio': ratio, 'raw_output': output }) return PingHandler class ThreadingHTTPServer(socketserver.ThreadingMixIn, HTTPServer): daemon_threads = True if __name__ == '__main__': topo = PentagonTopo() ctrl = RemoteController('ryu', ip='172.254.252.10', port=6653) Loading @@ -56,10 +137,19 @@ if __name__ == '__main__': net.start() net.staticArp() ping_handler = build_http_handler(net) http_server = ThreadingHTTPServer(('0.0.0.0', 5000), ping_handler) server_thread = threading.Thread(target=http_server.serve_forever, daemon=True) server_thread.start() print('Custom Pentagon Topology is up with static ARP.') #CLI(net) print('HTTP ping server running at http://0.0.0.0:5000/ping?source=h1&target=h2&count=3') try: while True: time.sleep(60) #while True: #time.sleep(60) #net.stop() except KeyboardInterrupt: print('Stopping Mininet...') http_server.shutdown() http_server.server_close() net.stop()