向连接Docker主机的OVS交换机自动添加流及SDN拓扑配置咨询
Hey there! Based on your setup—one OVS switch linking two Docker containers and connected to OpenDaylight (ODL)—here are several practical, actionable solutions to automate flow entry addition, tailored to your use case:
1. Use OpenDaylight's REST Northbound API (Recommended for SDN-Native Workflows)
Since your OVS is already connected to ODL, leveraging ODL's REST API is the most integrated approach. ODL maintains full control over the switch, so you can push flows directly through the controller without bypassing its management plane.
Step-by-Step Implementation:
- First, confirm ODL's RESTCONF feature is enabled (it's included in most standard distributions like
odl-l2switch-all). - Use
curl(or any HTTP client) to send POST requests to ODL's REST endpoint. Below is an example to add bidirectional flows for your two containers:
# Add flow from HOST1 (OVS port 1) to HOST2 (OVS port 2) curl -u admin:admin -X POST \ http://<ODL_IP>:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/1 \ -H "Content-Type: application/json" \ -d '{ "flow": [ { "id": "1", "match": { "in-port": "1", "ethernet-match": { "ethernet-source": {"address": "<HOST1_MAC>"}, "ethernet-destination": {"address": "<HOST2_MAC>"} } }, "instructions": { "instruction": [ { "order": "0", "apply-actions": { "action": [ { "order": "0", "output-action": {"output-node-connector": "2"} } ] } } ] }, "priority": "1000", "table_id": "0" } ] }' # Add reverse flow from HOST2 (OVS port 2) to HOST1 (OVS port 1) curl -u admin:admin -X POST \ http://<ODL_IP>:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/2 \ -H "Content-Type: application/json" \ -d '{ "flow": [ { "id": "2", "match": { "in-port": "2", "ethernet-match": { "ethernet-source": {"address": "<HOST2_MAC>"}, "ethernet-destination": {"address": "<HOST1_MAC>"} } }, "instructions": { "instruction": [ { "order": "0", "apply-actions": { "action": [ { "order": "0", "output-action": {"output-node-connector": "1"} } ] } } ] }, "priority": "1000", "table_id": "0" } ] }'
- Replace
<ODL_IP>,<HOST1_MAC>,<HOST2_MAC>with your actual values. Grab container MACs withdocker inspect host1 | grep MacAddress. - To automate this, save the commands into a shell script and run it on ODL startup (e.g., add it to ODL's post-startup hooks) or trigger it via a cron job.
2. Shell Script with ovs-ofctl (Direct OVS Control)
If you need a lightweight, controller-agnostic option, use ovs-ofctl to push flows directly to OVS. Note: ODL may overwrite these flows if it's configured to fully manage the switch, so this works best for temporary or standalone automation.
Example Script:
#!/bin/bash # Define variables OVS_SWITCH="s1" # Get OVS port IDs linked to containers HOST1_PORT=$(ovs-vsctl list interface | grep -B2 -A2 "host1" | grep port_no | awk '{print $3}') HOST2_PORT=$(ovs-vsctl list interface | grep -B2 -A2 "host2" | grep port_no | awk '{print $3}') # Get container MAC addresses HOST1_MAC=$(docker inspect host1 | grep MacAddress | awk -F'"' '{print $4}') HOST2_MAC=$(docker inspect host2 | grep MacAddress | awk -F'"' '{print $4}') # Add forward flow ovs-ofctl add-flow $OVS_SWITCH "table=0, priority=1000, in_port=$HOST1_PORT, dl_src=$HOST1_MAC, dl_dst=$HOST2_MAC, actions=output:$HOST2_PORT" # Add reverse flow ovs-ofctl add-flow $OVS_SWITCH "table=0, priority=1000, in_port=$HOST2_PORT, dl_src=$HOST2_MAC, dl_dst=$HOST1_MAC, actions=output:$HOST1_PORT"
- Make the script executable with
chmod +x add_flows.sh - Automate execution by adding it to
/etc/rc.local(for system startup) or creating a systemd service for more reliable management.
3. Python Script for Dynamic Automation
For flexible, event-driven automation (e.g., updating flows when containers start/stop), use a Python script to interact with both Docker and ODL/OVS APIs.
Example Using requests (ODL API) and Docker SDK:
import requests import docker # ODL Configuration ODL_URL = "http://<ODL_IP>:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow" ODL_AUTH = ("admin", "admin") HEADERS = {"Content-Type": "application/json"} # Initialize Docker client client = docker.from_env() def get_container_mac(container_name): """Fetch MAC address of a Docker container""" container = client.containers.get(container_name) return container.attrs['NetworkSettings']['Networks']['none']['MacAddress'] def add_odl_flow(flow_id, in_port, src_mac, dst_mac, out_port): """Push flow entry to ODL via REST API""" flow_payload = { "flow": [ { "id": str(flow_id), "match": { "in-port": str(in_port), "ethernet-match": { "ethernet-source": {"address": src_mac}, "ethernet-destination": {"address": dst_mac} } }, "instructions": { "instruction": [ { "order": "0", "apply-actions": { "action": [ { "order": "0", "output-action": {"output-node-connector": str(out_port)} } ] } } ] }, "priority": "1000", "table_id": "0" } ] } response = requests.post(f"{ODL_URL}/{flow_id}", auth=ODL_AUTH, headers=HEADERS, json=flow_payload) return response.status_code # Get MAC addresses for containers host1_mac = get_container_mac("host1") host2_mac = get_container_mac("host2") # Add bidirectional flows (replace port numbers with your OVS port IDs) add_odl_flow(1, 1, host1_mac, host2_mac, 2) add_odl_flow(2, 2, host2_mac, host1_mac, 1) print("Flows added successfully!")
- Install required packages:
pip install requests docker - Trigger this script on container startup using Docker's
--entrypointor use a tool likewatchdogto monitor container state changes.
内容的提问来源于stack exchange,提问作者nephilim_boy

