练习:qos
本教程的目的是扩展基本的L3转发 ,使用区别服务实现服务质量(QOS)。 Diffserv简单且可扩展。 它对网络流量进行分类和管理,并在现代IP网络上提供QOS。
拓扑图代码
{
"hosts": {
"h1": {"ip": "10.0.1.1/31", "mac": "08:00:00:00:01:01",
"commands":["route add default gw 10.0.1.0 dev eth0",
"arp -i eth0 -s 10.0.1.0 08:00:00:00:01:00"]},
"h11": {"ip": "10.0.1.11/31", "mac": "08:00:00:00:01:11",
"commands":["route add default gw 10.0.1.10 dev eth0",
"arp -i eth0 -s 10.0.1.10 08:00:00:00:01:00"]},
"h2": {"ip": "10.0.2.2/31", "mac": "08:00:00:00:02:02",
"commands":["route add default gw 10.0.2.3 dev eth0",
"arp -i eth0 -s 10.0.2.3 08:00:00:00:02:00"]},
"h22": {"ip": "10.0.2.22/31", "mac": "08:00:00:00:02:22",
"commands":["route add default gw 10.0.2.23 dev eth0",
"arp -i eth0 -s 10.0.2.23 08:00:00:00:02:00"]},
"h3": {"ip": "10.0.3.3/31", "mac": "08:00:00:00:03:03",
"commands":["route add default gw 10.0.3.2 dev eth0",
"arp -i eth0 -s 10.0.3.2 08:00:00:00:03:00"]}
},
"switches": {
"s1": { "runtime_json" : "s1-runtime.json" },
"s2": { "runtime_json" : "s2-runtime.json" },
"s3": { "runtime_json" : "s3-runtime.json" }
},
"links": [
["h1", "s1-p2"], ["h11", "s1-p1"], ["s1-p3", "s2-p3"], ["s1-p4", "s3-p2"],
["s3-p3", "s2-p4"], ["h2", "s2-p2"], ["h22", "s2-p1"], ["h3", "s3-p1"]
]
}
P4文件代码
#include <core.p4>
#include <v1model.p4>
const bit<16> TYPE_IPV4 = 0x800;
const bit<8> IP_PROTOCOLS_ICMP = 1;
const bit<8> IP_PROTOCOLS_IGMP = 2;
const bit<8> IP_PROTOCOLS_IPV4 = 4;
const bit<8> IP_PROTOCOLS_TCP = 6;
const bit<8> IP_PROTOCOLS_UDP = 17;
const bit<8> IP_PROTOCOLS_IPV6 = 41;
const bit<8> IP_PROTOCOLS_GRE = 47;
const bit<8> IP_PROTOCOLS_IPSEC_ESP = 50;
const bit<8> IP_PROTOCOLS_IPSEC_AH = 51;
const bit<8> IP_PROTOCOLS_ICMPV6 = 58;
const bit<8> IP_PROTOCOLS_EIGRP = 88;
const bit<8> IP_PROTOCOLS_OSPF = 89;
const bit<8> IP_PROTOCOLS_PIM = 103;
const bit<8> IP_PROTOCOLS_VRRP = 112;
typedef bit<9> egressSpec_t;
typedef bit<48> macAddr_t;
typedef bit<32> ip4Addr_t;
header ethernet_t {
macAddr_t dstAddr;
macAddr_t srcAddr;
bit<16> etherType;
}
header ipv4_t {
bit<4> version;
bit<4> ihl;
bit<6> diffserv;
bit<2> ecn;
bit<16> totalLen;
bit<16> identification;
bit<3> flags;
bit<13> fragOffset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdrChecksum;
ip4Addr_t srcAddr;
ip4Addr_t dstAddr;
}
struct metadata {
}
struct headers {
ethernet_t ethernet;
ipv4_t ipv4;
}
parser MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
state start {
transition parse_ethernet;
}
state parse_ethernet {
packet.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType) {
TYPE_IPV4: parse_ipv4;
default: accept;
}
}
state parse_ipv4 {
packet.extract(hdr.ipv4);
transition accept;
}
}
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
apply { }
}
control MyIngress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
action drop() {
mark_to_drop(standard_metadata);
}
action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {
standard_metadata.egress_spec = port;
hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
hdr.ethernet.dstAddr = dstAddr;
hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
}
action default_forwarding() {
hdr.ipv4.diffserv = 0;
}
action expedited_forwarding() {
hdr.ipv4.diffserv = 46;
}
action voice_admit() {
hdr.ipv4.diffserv = 44;
}
action af_11() {
hdr.ipv4.diffserv = 10;
}
action af_12() {
hdr.ipv4.diffserv = 12;
}
action af_13() {
hdr.ipv4.diffserv = 14;
}
action af_21() {
hdr.ipv4.diffserv = 18;
}
action af_22() {
hdr.ipv4.diffserv = 20;
}
action af_23() {
hdr.ipv4.diffserv = 22;
}
action af_31() {
hdr.ipv4.diffserv = 26;
}
action af_32() {
hdr.ipv4.diffserv = 28;
}
action af_33() {
hdr.ipv4.diffserv = 30;
}
action af_41() {
hdr.ipv4.diffserv = 34;
}
action af_42() {
hdr.ipv4.diffserv = 36;
}
action af_43() {
hdr.ipv4.diffserv = 38;
}
table ipv4_lpm {
key = {
hdr.ipv4.dstAddr: lpm;
}
actions = {
ipv4_forward;
drop;
NoAction;
}
size = 1024;
default_action = NoAction();
}
apply {
if (hdr.ipv4.isValid()) {
if (hdr.ipv4.protocol == IP_PROTOCOLS_UDP) {
expedited_forwarding();
}
else if (hdr.ipv4.protocol == IP_PROTOCOLS_TCP) {
voice_admit();
}
ipv4_lpm.apply();
}
}
}
control MyEgress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
apply { }
}
control MyComputeChecksum(inout headers hdr, inout metadata meta) {
apply {
update_checksum(
hdr.ipv4.isValid(),
{ hdr.ipv4.version,
hdr.ipv4.ihl,
hdr.ipv4.diffserv,
hdr.ipv4.ecn,
hdr.ipv4.totalLen,
hdr.ipv4.identification,
hdr.ipv4.flags,
hdr.ipv4.fragOffset,
hdr.ipv4.ttl,
hdr.ipv4.protocol,
hdr.ipv4.srcAddr,
hdr.ipv4.dstAddr },
hdr.ipv4.hdrChecksum,
HashAlgorithm.csum16);
}
}
control MyDeparser(packet_out packet, in headers hdr) {
apply {
packet.emit(hdr.ethernet);
packet.emit(hdr.ipv4);
}
}
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
交换机控制器代码
{
"target": "bmv2",
"p4info": "build/qos.p4.p4info.txt",
"bmv2_json": "build/qos.json",
"table_entries": [
{
"table": "MyIngress.ipv4_lpm",
"match": {
"hdr.ipv4.dstAddr": ["10.0.1.1", 32]
},
"action_name": "MyIngress.ipv4_forward",
"action_params": {
"dstAddr": "08:00:00:00:01:01",
"port": 2
}
},
{
"table": "MyIngress.ipv4_lpm",
"match": {
"hdr.ipv4.dstAddr": ["10.0.1.11", 32]
},
"action_name": "MyIngress.ipv4_forward",
"action_params": {
"dstAddr": "08:00:00:00:01:11",
"port": 1
}
},
{
"table": "MyIngress.ipv4_lpm",
"match": {
"hdr.ipv4.dstAddr": ["10.0.2.0", 24]
},
"action_name": "MyIngress.ipv4_forward",
"action_params": {
"dstAddr": "08:00:00:00:02:00",
"port": 3
}
},
{
"table": "MyIngress.ipv4_lpm",
"match": {
"hdr.ipv4.dstAddr": ["10.0.3.0", 24]
},
"action_name": "MyIngress.ipv4_forward",
"action_params": {
"dstAddr": "08:00:00:00:03:00",
"port": 4
}
}
]
}
发送方代码
import argparse
import socket
from scapy.all import sendp, send, hexdump, get_if_list, get_if_hwaddr
from scapy.all import Ether, IP, UDP, TCP
from time import sleep
def get_if():
iface = None
for i in get_if_list():
if "eth0" in i:
iface = i
break
if not iface:
print("Cannot find eth0 interface")
exit(1)
return iface
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--p", help="Protocol name To send TCP/UDP etc packets", type=str)
parser.add_argument("--des", help="IP address of the destination", type=str)
parser.add_argument("--m", help="Raw Message", type=str)
parser.add_argument("--dur", help="in seconds", type=str)
args = parser.parse_args()
if args.p and args.des and args.m and args.dur:
addr = socket.gethostbyname(args.des)
iface = get_if()
if args.p == 'UDP':
pkt = Ether(src=get_if_hwaddr(iface), dst="ff:ff:ff:ff:ff:ff") / IP(dst=addr, tos=1) / UDP(dport=4321, sport=1234) / args.m
pkt.show2()
try:
for i in range(int(args.dur)):
sendp(pkt, iface=iface)
sleep(1)
except KeyboardInterrupt:
raise
elif args.p == 'TCP':
pkt = Ether(src=get_if_hwaddr(iface), dst="ff:ff:ff:ff:ff:ff") / IP(dst=addr, tos=1) / TCP() / args.m
pkt.show2()
try:
for i in range(int(args.dur)):
sendp(pkt, iface=iface)
sleep(1)
except KeyboardInterrupt:
raise
if __name__ == '__main__':
main()
|