Network Function Virtualization --- monitor

 

[Description]

 

When a sender talks to a receiver, the packets go through different network elements, such as IDS, IPS, or firewall. However, different kinds of packets may have different policies. Some packets can go directly to the receiver, and some packets may need to go through firewall or IDP(IPS) to do deep packet inspection (DPI). In order to provide more flexible services to customers, SDN + NFV would be one of solutions. We can implement different network functions, such as IDP, IPS, firewall in VM or docker. Then use openflow to dynamically change the routing path for different packets to those network elements, and finally reach the destination.

 

In this lab, the h1 will talk to h3 first. Then we can dynamically divert the packets to h2 for monitor and then reach the h3.

 

There are three scripts. The first one is talk to controller to set up the rules for h1 and h3 communication. The second one is to divert the packets to h2 first and then to h3. The third is to delete the divert function and restore to original rules for h1 and h3 communication.

 

[monitor1_setup_rules.py]

import urllib2 

import json 

 

def get_all_switches(): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_all_links(): 

    url = "http://127.0.0.1:8080/v1.0/topology/links" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

def get_switch(dpid): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_flow_entries(dpid): 

    url = "http://127.0.0.1:8080/stats/flow/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def add_flow_entry(dpid,match,priority,actions): 

    url = "http://127.0.0.1:8080/stats/flowentry/add" 

    post_data = "{'dpid':%s,'match':%s,'priority':%s,'actions':%s}" % (dpid,str(match),priority,str(actions)) 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode() 

 

def delete_flow_entry(dpid, match=None, priority=None, actions=None): 

    url = "http://127.0.0.1:8080/stats/flowentry/delete" 

    post_data = "{'dpid':%s" % dpid 

    if match is not None: 

        post_data += ",'match':%s" % str(match) 

    if priority is not None: 

        post_data += ",'priority':%s" % priority 

    if actions is not None: 

        post_data += ",'actions':%s" % str(actions) 

    post_data += "}" 

 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode()

 

 

#h1----s1----h3

#      |

#      h2

# h1 talks to h3

 

#rule0: priority=0,arp,actions=output:flood

#rule1: priority=10,icmp,in_port=1,actions=output:3

#rule2: priority=10,icmp,in_port=3,actions=output:1

 

print "add_flow_entry(dpid,match,priority,actions)"

 

print add_flow_entry('0000000000000001',{"dl_type": 2054},1,[{"type":"OUTPUT","port":0xfffffffb}])

 

print add_flow_entry('0000000000000001',{"in_port":00000001,"dl_type":2048,"nw_proto":1},1,[{"type":"OUTPUT","port":00000003}])

print add_flow_entry('0000000000000001',{"in_port":00000003,"dl_type":2048,"nw_proto":1},1,[{"type":"OUTPUT","port":00000001}])

 

 

[monitor2_divert_h2.py]

import urllib2 

import json 

 

def get_all_switches(): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_all_links(): 

    url = "http://127.0.0.1:8080/v1.0/topology/links" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

def get_switch(dpid): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.u#h1----s1----h3

#      |

#      h2

# h1 talks to h3

 

#rule2: priority=10,icmp,in_port=1,actions=output:3

#rule3: priority=10,icmp,in_port=3,actions=output:1rlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_flow_entries(dpid): 

    url = "http://127.0.0.1:8080/stats/flow/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def add_flow_entry(dpid,match,priority,actions): 

    url = "http://127.0.0.1:8080/stats/flowentry/add" 

    post_data = "{'dpid':%s,'match':%s,'priority':%s,'actions':%s}" % (dpid,str(match),priority,str(actions)) 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode() 

 

def delete_flow_entry(dpid, match=None, priority=None, actions=None): 

    url = "http://127.0.0.1:8080/stats/flowentry/delete" 

    post_data = "{'dpid':%s" % dpid 

    if match is not None: 

        post_data += ",'match':%s" % str(match) 

    if priority is not None: 

        post_data += ",'priority':%s" % priority 

    if actions is not None: 

        post_data += ",'actions':%s" % str(actions) 

    post_data += "}" 

 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode()

 

 

#h1----s1----h3

#      |

#      h2

# h1 talks to h3

 

#rule0: priority=0,arp,actions=output:flood

#rule1: priority=10,icmp,in_port=1,actions=output:3

#rule2: priority=10,icmp,in_port=3,actions=output:1

#rule3: priority=20,in_port=1,icmp,actions=mod_dl_dst=00:00:00:00:00:02,output:2

#rule4: priority=20,in_port=2,icmp,dl_dst=00:00:00:00:00:03,output:3

#rule5: priority=20,in_port=3,icmp,actions=mod_dl_dst=00:00:00:00:00:02,output:2

#rule6: priority=20,in_port=2,icmp,dl_dst=00:00:00:00:00:01,output:1

 

print "add_flow_entry(dpid,match,priority,actions)"

 

print add_flow_entry('0000000000000001',{"in_port":00000001,"dl_dst": "00:00:00:00:00:03","dl_type":2048,"nw_proto":1},20,[{"type": "SET_DL_DST", "dl_dst": "00:00:00:00:00:02"},{"type":"OUTPUT","port":00000002}])

 

print add_flow_entry('0000000000000001',{"in_port":00000002,"dl_dst": "00:00:00:00:00:03","dl_type":2048,"nw_proto":1},20,[{"type":"OUTPUT","port":00000003}])

 

print add_flow_entry('0000000000000001',{"in_port":00000003,"dl_dst": "00:00:00:00:00:01","dl_type":2048,"nw_proto":1},20,[{"type": "SET_DL_DST", "dl_dst": "00:00:00:00:00:02"},{"type":"OUTPUT","port":00000002}])

 

print add_flow_entry('0000000000000001',{"in_port":00000002,"dl_dst": "00:00:00:00:00:01","dl_type":2048,"nw_proto":1},20,[{"type":"OUTPUT","port":00000001}])

 

 

[monitor3_del_monitor.py]

import urllib2 

import json 

 

def get_all_switches(): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_all_links(): 

    url = "http://127.0.0.1:8080/v1.0/topology/links" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

def get_switch(dpid): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_flow_entries(dpid): 

    url = "http://127.0.0.1:8080/stats/flow/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def add_flow_entry(dpid,match,priority,actions): 

    url = "http://127.0.0.1:8080/stats/flowentry/add" 

    post_data = "{'dpid':%s,'match':%s,'priority':%s,'actions':%s}" % (dpid,str(match),priority,str(actions)) 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode() 

 

def delete_flow_entry(dpid, match=None, priority=None, actions=None): 

    url = "http://127.0.0.1:8080/stats/flowentry/delete" 

    post_data = "{'dpid':%s" % dpid 

    if match is not None:  

        post_data += ",'match':%s" % str(match) 

    if priority is not None: 

        post_data += ",'priority':%s" % priority 

    if actions is not None: 

        post_data += ",'actions':%s" % str(actions) 

    post_data += "}" 

 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode()

 

 

#h1----s1----h3

#      |

#      h2

# h1 talks to h3

 

 

print "delete_flow_entry(dpid, match=None, priority=None, actions=None)"

 

print delete_flow_entry('0000000000000001',{"in_port":00000001,"dl_dst": "00:00:00:00:00:03","dl_type":2048,"nw_proto":1})

 

print delete_flow_entry('0000000000000001',{"in_port":00000002,"dl_dst": "00:00:00:00:00:03","dl_type":2048,"nw_proto":1})

 

print delete_flow_entry('0000000000000001',{"in_port":00000003,"dl_dst": "00:00:00:00:00:01","dl_type":2048,"nw_proto":1})

 

print delete_flow_entry('0000000000000001',{"in_port":00000002,"dl_dst": "00:00:00:00:00:01","dl_type":2048,"nw_proto":1,})

 

#print add_flow_entry('0000000000000001',{"in_port":00000001,"dl_type":2048,"nw_proto":1},1,[{"type":"OUTPUT","port":00000003}])

 

#print add_flow_entry('0000000000000001',{"in_port":00000003,"dl_type":2048,"nw_proto":1},1,[{"type":"OUTPUT","port":00000001}])

 

[execution]

Open three terminals. In first terminal.

 

In the second terminal

 

In the third terminal to run the first script. Then we can try to ping h3 from h1 in the second terminal.

 

 

Now open terminal for h1 and h2 in the second terminal.

 

In h2, we run the tcpdump to monitor packets and ping in h1 terminal.

We can see nothing about icmp packets in h2 terminal now. So run the monitor2_divert_h2.py in the third terminal.

 

Then we can see icmp packets in h2. (Monitor Function has been implemented)

 

Run the last script.

 

No icmp packets can be seen in h2 again. But h1 still pings h3.

 

[references]

http://blog.csdn.net/sdnexplorer/article/details/46709801

 

Dr. Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Kinmen, Taiwan

Email: smallko@gmail.com / smallko@nqu.edu.tw