本教程的目的是扩展基本的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交换机控制器代码#include 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
}
}
]
}
发送方代码
#!/usr/bin/env python3
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()



