Thực thi ứng dụng SDN Northbound qua REST API với OpenDaylight và Ryu

Tương tác với Controller OpenDaylight qua Northbound API

Việc quản trị mạng SDN thông qua các giao diện lập trình ứng dụng (API) hướng Bắc cho phép lập trình viên điều khiển cấu hình thiết bị một cách linh hoạt. Dưới đây là các ví dụ thực thi sử dụng thư viện requests trong Python để tương tác với OpenDaylight.

1. Xóa toàn bộ dữ liệu bảng luồng trên Switch s1

Để dọn dẹp các flow entry cũ trên một node cụ thể (ví dụ openflow:1), chúng ta sử dụng phương thức DELETE của HTTP.

import requests
from requests.auth import HTTPBasicAuth

def clear_switch_flows(controller_ip, dpid):
    target_url = f'http://{controller_ip}:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:{dpid}/'
    headers = {'Content-Type': 'application/json'}
    response = requests.delete(target_url, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
    return response.status_code

if __name__ == "__main__":
    status = clear_switch_flows('127.0.0.1', 1)
    print(f"Kết quả thực thi: {status}")

2. Thiết lập Hard Timeout để ngắt kết nối giữa h1 và h3

Bằng cách đẩy một flow rule có thuộc tính hard-timeout là 20 giây và hành động drop, chúng ta có thể tạm ngừng giao thông mạng giữa các host chỉ định.

import requests
import json
from requests.auth import HTTPBasicAuth

def deploy_timeout_flow():
    node_url = 'http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/1'
    
    flow_payload = {
        "flow": [{
            "id": "1",
            "table_id": "0",
            "priority": "65535",
            "hard-timeout": "20",
            "match": {
                "ethernet-match": {"ethernet-type": {"type": "0x0800"}},
                "ipv4-destination": "10.0.0.3/32"
            },
            "instructions": {
                "instruction": [{
                    "order": "0",
                    "apply-actions": {
                        "action": [{"order": "0", "drop-action": {}}]
                    }
                }]
            }
        }]
    }
    
    auth = HTTPBasicAuth('admin', 'admin')
    headers = {'Content-Type': 'application/json'}
    res = requests.put(node_url, data=json.dumps(flow_payload), headers=headers, auth=auth)
    print(f"Trạng thái phản hồi: {res.status_code}")

if __name__ == "__main__":
    deploy_timeout_flow()

3. Truy vấn số lượng bảng luồng đang hoạt động

Sử dụng API trạng thái (operational data) để lấy thống kê về các flow đang tồn tại trên thiết bị.

import requests
from requests.auth import HTTPBasicAuth

def get_active_flow_count(node_id):
    endpoint = f'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:{node_id}/flow-node-inventory:table/0/opendaylight-flow-table-statistics:flow-table-statistics'
    headers = {'Content-Type': 'application/json'}
    resp = requests.get(endpoint, headers=headers, auth=HTTPBasicAuth('admin', 'admin'))
    return resp.json()

if __name__ == "__main__":
    stats = get_active_flow_count(1)
    print(stats)

Điều khiển Controller Ryu thông qua REST API

Ryu cung cấp module ofctl_rest.py để người dùng có thể thực hiện các thao tác quản lý OpenFlow qua HTTP POST/GET.

1. Đẩy luật chặn lưu lượng có thời hạn

Dưới đây là cách thực hiện việc chặn cổng đầu vào số 1 trong vòng 20 giây.

import requests
import json

def push_ryu_timeout():
    api_url = 'http://127.0.0.1:8080/stats/flowentry/add'
    rule_data = {
        "dpid": 1,
        "table_id": 0,
        "hard_timeout": 20,
        "priority": 65535,
        "match": {"in_port": 1},
        "actions": []
    }
    response = requests.post(api_url, data=json.dumps(rule_data))
    print(f"Kết quả từ Ryu: {response.status_code}")

if __name__ == "__main__":
    push_ryu_timeout()

2. Cấu hình phân đoạn mạng VLAN

Việc gán VLAN ID và gắn/gỡ thẻ (Tagging/Untagging) được thực hiện bằng cách điều chỉnh các hành động PUSH_VLANSET_FIELD.

import requests
import json

def setup_vlan_config():
    api_endpoint = 'http://127.0.0.1:8080/stats/flowentry/add'
    
    # Định nghĩa danh sách các quy tắc VLAN
    vlan_rules = [
        # Switch 1: Port 1 -> VLAN 4096, Port 2 -> VLAN 4097
        {"dpid": 1, "match": {"in_port": 1}, "actions": [{"type": "PUSH_VLAN", "ethertype": 33024}, {"type": "SET_FIELD", "field": "vlan_vid", "value": 4096}, {"type": "OUTPUT", "port": 3}]},
        {"dpid": 1, "match": {"in_port": 2}, "actions": [{"type": "PUSH_VLAN", "ethertype": 33024}, {"type": "SET_FIELD", "field": "vlan_vid", "value": 4097}, {"type": "OUTPUT", "port": 3}]},
        # Pop VLAN khi ra khỏi các port tương ứng
        {"dpid": 1, "match": {"vlan_vid": 4096}, "actions": [{"type": "POP_VLAN"}, {"type": "OUTPUT", "port": 1}]},
        {"dpid": 1, "match": {"vlan_vid": 4097}, "actions": [{"type": "POP_VLAN"}, {"type": "OUTPUT", "port": 2}]}
    ]

    for rule in vlan_rules:
        rule["priority"] = 100
        requests.post(api_endpoint, data=json.dumps(rule))

if __name__ == "__main__":
    setup_vlan_config()

Phân tích hệ thống mạng và trích xuất bảng luồng

Sử dụng một kịch bản Python hợp nhất để truy vấn danh sách các thiết bị chuyển mạch và các luật hiện có trong toàn bộ mạng SDN do Ryu quản lý.

import requests

class SDNAuditor:
    def __init__(self, controller_addr):
        self.base_url = f"http://{controller_addr}"

    def list_switches(self):
        resp = requests.get(f"{self.base_url}/stats/switches")
        return resp.json()

    def fetch_all_flows(self):
        switches = self.list_switches()
        network_inventory = {}
        
        for sw_id in switches:
            flow_url = f"{self.base_url}/stats/flow/{sw_id}"
            flows = requests.get(flow_url).json()
            network_inventory[sw_id] = flows
            
        return network_inventory

    def display_report(self):
        inventory = self.fetch_all_flows()
        for dpid, flows in inventory.items():
            print(f"--- Thiết bị [s{dpid}] ---")
            for entry in flows[str(dpid)]:
                print(f"  Rule: {entry}")

if __name__ == "__main__":
    auditor = SDNAuditor("127.0.0.1:8080")
    auditor.display_report()

Thẻ: SDN OpenDaylight Ryu OpenFlow rest-api

Đăng vào ngày 31 tháng 7 lúc 00:39