RYU实战,REST API流表控制(1)

前言

本月上旬到海南出差,现在回来终于可以继续乱入SDN了。本次学习的是如何使用RYU提供的REST API接口对交换机的流表进行控制。对流表的控制无外呼就是增删改查了。本节先使用POSTMAN进行实验,体验一下效果。下一节将使用写一个可视化工具封装一下REST API,方便后续的调试与开发。

实验拓扑

控制器:RYU
交换机:s1,s2
主机:h1,h2,h3,h3
联通性(直连):
h1<->s1;h2<->s1
h3<->s2;h4<->s2
s1<->s2
拓扑代码如下:

__author__ = 'jmh081701'
from mininet.topo import Topo
class MyTopo(Topo):
    def __init__(self):
        Topo.__init__(self)
        left=[]
        left.append(self.addHost("h1"))
        left.append(self.addHost("h2"))
        right=[]
        right.append(self.addHost("h3"))
        right.append(self.addHost("h4"))
        switchs=[]
        switchs.append(self.addSwitch("s1"))
        switchs.append(self.addSwitch("s2"))

        self.addLink(left[0],switchs[0])
        self.addLink(left[1],switchs[0])
        self.addLink(right[0],switchs[1])
        self.addLink(right[1],switchs[1])
        self.addLink(switchs[0],switchs[1])


topos={'mytopo':(lambda : MyTopo())}

启动ryu

cd RYUPATH/ryu/app/         #首先进入到RYU的安装目录的app目录下,里面有相应的模块
sudo ryu-manager ofctl_rest.py simple_switch.py
# 启动ofctl_rest.py模块以及simple_switch.py交换机,这个是openflow1.0的交换机

启动mininet

sudo mn --controller=remote,ip=192.168.1.197,port=6653 --custom 1.py --topo mytopo 

其中 1.py是刚刚定义的拓扑python文件, mytopo是 最后两行

topos={'mytopo':(lambda : MyTopo())} 中指定的拓扑名

注意 这里面有一个坑!!!
加载自定义拓扑文件时 是使用 –custom .py 格式,而不是– custom=.py 格式 –topo 也是类似。
mn –help 出来的结果是:

  --topo=TOPO           linear|minimal|reversed|single|tree[,param=value...]
  -c, --clean           clean and exit
  --custom=CUSTOM       read custom topo and node params from .py

然而 – custom=*.py 是不能加载的

实验细节

1. 在mininet 检查网络联通性

mininet> pingall
*** Ping: testing ping reachability
h1 -> h2 h3 h4 
h2 -> h1 h3 h4 
h3 -> h1 h2 h4 
h4 -> h1 h2 h3 
*** Results: 0% dropped (12/12 received)

结论:4台主机 两两互通

2. 分析得到各网络节点的地址(不知道是不是MAC地址,因为交换机居然也有这个地址)

h1-eth0: fe:3b:25:cc:04:97
h2-eth0: d2:3e:55:89:f3:a1
h3-eth0: 02:28:7c:93:27:af
h4-eth0: ba:94:88:a1:55:63

3. 流表”查”

打开chrome的扩展工具 postman

3.1 得到所有交换机列表:

URL: http://192.168.1.197:8080/stats/switches
使用GET方法
结果:

[
  1,
  2
]

得到一个json list,里面有两个元素:1和2,表示共有两台交换机。
这是他们的DPID,datapath id

3.2 得到某台交换机状态信息

URL : http://192.168.1.197:8080:/stats/desc/
方法:get
其中 是可变的,由3.1 所得填入即可
比如得到交换机1的基本信息:
URL http://192.168.1.197:8080/stats/desc/1
结果:

{
  "1":(DPID) 
  {
    "dp_desc": "None",(datapath的描述信息)
    "sw_desc": "2.0.2",(软件机的描述信息)
    "hw_desc": "Open vSwitch",(交换机描述信息)
    "serial_num": "None",(序列号)
    "mfr_desc": "Nicira, Inc."(生产商信息)
  }
}

3.3 得到指定交换机的所有flow的状态信息

URL: http://192.168.1.197:8080/stats/flow/
方法:GET
如得到交换机1的所有流表项:

{
  "1": [
    {
      "actions": [
        "OUTPUT:3"
      ],(动作,转发到3 号端口)
      "idle_timeout": 0,(空闲后存活时间)
      "cookie": 0,
      "packet_count": 2,(包计数)
      "hard_timeout": 0,(存活时间)
      "byte_count": 140,(比特计数)
      "duration_nsec": 111000000,
      "priority": 32768,(优先级)
      "duration_sec": 985,(已经存活时间)
      "table_id": 0,(在流表1"match": (匹配字段)
      {
        "dl_dst": "02:28:7c:93:27:af",(过滤目的地址为02:28:7c:93:27:af的包,就是去主机3的包)
        "in_port": 2(从2号口子来的)
      }
      (作用:从2号口子来的,要到h3的报文都从3号口子出去哈)
    },
    {
      "actions": [
        "OUTPUT:2"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 7,
      "hard_timeout": 0,
      "byte_count": 518,
      "duration_nsec": 113000000,
      "priority": 32768,
      "duration_sec": 985,
      "table_id": 0,
      "match": {
        "dl_dst": "d2:3e:55:89:f3:a1",
        "in_port": 3
      }
      (作用:从3号口子来的,发往h2的包都从2号口子出去哈)
    },
    {
      "actions": [
        "OUTPUT:3"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 2,
      "hard_timeout": 0,
      "byte_count": 140,
      "duration_nsec": 155000000,
      "priority": 32768,
      "duration_sec": 985,
      "table_id": 0,
      "match": {
        "dl_dst": "02:28:7c:93:27:af",
        "in_port": 1
      }
      (作用:1号口子来的,发往h3的的包都从3号口子出去哈
    },
    {
      "actions": [
        "OUTPUT:1"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 3,
      "hard_timeout": 0,
      "byte_count": 238,
      "duration_nsec": 171000000,
      "priority": 32768,
      "duration_sec": 985,
      "table_id": 0,
      "match": {
        "dl_dst": "fe:3b:25:cc:04:97",
        "in_port": 2
      }
      (作用:从2号口子来的,发往h1的包都从1号口子出去哈)
    },
    {
      "actions": [
        "OUTPUT:2"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 2,
      "hard_timeout": 0,
      "byte_count": 140,
      "duration_nsec": 169000000,
      "priority": 32768,
      "duration_sec": 985,
      "table_id": 0,
      "match": {
        "dl_dst": "d2:3e:55:89:f3:a1",
        "in_port": 1
      }
      (从1号口子来的,发给h2的包都从2号口子出去哈
    },
    {
      "actions": [
        "OUTPUT:3"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 2,
      "hard_timeout": 0,
      "byte_count": 140,
      "duration_nsec": 137000000,
      "priority": 32768,
      "duration_sec": 985,
      "table_id": 0,
      "match": {
        "dl_dst": "ba:94:88:a1:55:63",
        "in_port": 1
      }
      (从1号口子来的,发往h4的,从3号口子出去哈)
    },
    {
      "actions": [
        "OUTPUT:1"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 7,
      "hard_timeout": 0,
      "byte_count": 518,
      "duration_nsec": 157000000,
      "priority": 32768,
      "duration_sec": 985,
      "table_id": 0,
      "match": {
        "dl_dst": "fe:3b:25:cc:04:97",
        "in_port": 3
      } 
      (作用:从3号口子来的,发给h1的包都从1号口子出去哈)
    },
    {
      "actions": [
        "OUTPUT:3"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 2,
      "hard_timeout": 0,
      "byte_count": 140,
      "duration_nsec": 92000000,
      "priority": 32768,
      "duration_sec": 985,
      "table_id": 0,
      "match": {
        "dl_dst": "ba:94:88:a1:55:63",
        "in_port": 2
      }
      (从2号口子来的,发给h4的都从3号口子出去哈)
    }
  ]
}

由上面,我们可以分析出:
第一个交换机一个有3个端口
端口1与h1直连
端口2与h2直连
端口3负责与另外一个交换机直连
另一个交换机也是类似的作法

3.3 有条件地查询某台交换机的流表

URL: http://192.168.1.197:8080/stats/flow/
方法:POST
其实就是通过POST一些过滤条件来返回结果,类似于SQL里面的where语句
支持的过滤字段有:

table_id:流表ID
out_port:出端口号
out_group:出组号
cookie:
cookie_mask:
match:匹配字段
prority:优先级

举个栗子:
我们想获取所以目的地为h1的流表项:只要过滤那些匹配域中目的为h1即可:
在BODY里面填:

{
    "match":
    {
    "dl_dst": "fe:3b:25:cc:04:97"
    }
}

结果:

{
  "1": [
    {
      "actions": [
        "OUTPUT:1"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 3,
      "hard_timeout": 0,
      "byte_count": 238,
      "duration_nsec": 426000000,
      "priority": 32768,
      "duration_sec": 3084,
      "table_id": 0,
      "match": {
        "dl_dst": "fe:3b:25:cc:04:97",
        "in_port": 2
      }
    },
    {
      "actions": [
        "OUTPUT:1"
      ],
      "idle_timeout": 0,
      "cookie": 0,
      "packet_count": 7,
      "hard_timeout": 0,
      "byte_count": 518,
      "duration_nsec": 412000000,
      "priority": 32768,
      "duration_sec": 3084,
      "table_id": 0,
      "match": {
        "dl_dst": "fe:3b:25:cc:04:97",
        "in_port": 3
      }
    }
  ]
}

把所有发给h1的流表项都过滤出来了

3.4 查询指定交换机的全局统计流表的字段

URL: http://192.168.1.197:8080/stats/aggregateflow/
方式:get
查交换机1的:

{
  "1": [
    {
      "packet_count": 27,
      "byte_count": 1974,
      "flow_count": 8
    }
  ]
}

可以看出是交换机所有流表项的全局性统计

3.5 有条件的查询指定交换机的全局统计流表的字段

与3.3方法类似,也是通过POST方法来过滤掉一些结果
过滤字段一样

3.6 查询指定交换机上所有流表的统计信息

URL: http://192.168.1.197:8080/stats/table/
方法:GET
比如查交换机1的流表相关信息

{
  "1": [
    {
      "wildcards": (通配符)
      [
        "IN_PORT",
        "DL_VLAN",
        "DL_SRC",
        "NW_DST_BITS",
        "NW_SRC_SHIFT",
        "NW_DST_SHIFT",
        "DL_TYPE"
      ],
      "matched_count": 12911,(已匹配计数)
      "name": "classifier",
      "active_count": 17,(有效的流表项)
      "max_entries": 1000000,
      "lookup_count": 13974,(查询计数)
      "table_id": 0(流表号)
    }
    ]
}

得到端口的统计信息

URL: http://192.168.1.197:8080/stats/port//[/]
方法:GET
得到指定交换机下的某端口统计信息(如果没有指定端口则获取所有端口)
如得到交换机1下端口1的:
http://192.168.1.197:8080/stats/port/1/1
结果:

{
  "1": [
    {
      "tx_dropped": 1,
      "rx_packets": 18,
      "rx_crc_err": 0,
      "tx_bytes": 219719,
      "rx_dropped": 0,
      "port_no": 1,
      "rx_over_err": 0,
      "rx_frame_err": 0,
      "rx_bytes": 1308,
      "tx_errors": 0,
      "collisions": 0,
      "rx_errors": 0,
      "tx_packets": 1176
    }
  ]
}

得到端口配置信息:

URL: http://192.168.1.197:8080/stats/portdesc/1
方法:GET
得到交换机1的结果:

{
  "1": [
    {
      "hw_addr": "1e:4f:eb:10:65:1c",
      "state": 0,
      "curr": 192,
      "name": "s1-eth1",
      "advertised": 0,
      "peer": 0,
      "supported": 0,
      "config": 0,
      "port_no": 1
    },
    {
      "hw_addr": "ee:09:8f:0d:35:5c",
      "state": 0,
      "curr": 192,
      "name": "s1-eth2",
      "advertised": 0,
      "peer": 0,
      "supported": 0,
      "config": 0,
      "port_no": 2
    },
    {
      "hw_addr": "96:e1:f6:ae:21:78",
      "state": 0,
      "curr": 192,
      "name": "s1-eth3",
      "advertised": 0,
      "peer": 0,
      "supported": 0,
      "config": 0,
      "port_no": 3
    },
    {
      "hw_addr": "2e:48:15:67:7f:43",
      "state": 0,
      "curr": 0,
      "name": "s1",
      "advertised": 0,
      "peer": 0,
      "supported": 0,
      "config": 0,
      "port_no": "LOCAL"
    }
  ]
}

你可能感兴趣的:(SDN)