p4实现负载均衡

实验要求

  • 基于简单版本的等成本多路径转发实现一种负载平衡。
  • 实现的交换机将使用两个表将数据包随机转发到两个目标主机之一
  • 第一个表将使用哈希函数(应用于由源和目标IP地址、IP协议以及源和目标TCP端口组成的5元组)来选择两个主机中的一个
  • 第二个表将使用计算的哈希值将数据包转发到所选主机

拓扑采用三角形拓扑结构,三个交换机互相连接,并各自接一个主机

实验内容

Step1:对照实验

首先,把不完全的p4交换机的mininet试运行一下,打开三个主机终端,我让h1发送信息到h2上,原来官方提供的我跑不了,所以随便补充了一个表上去,我反复使用了多次send,发现只能发送到h2上,说明负载不均衡

p4实现负载均衡_第1张图片

 

Step2:设计包头解析器,还有丢弃操作

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) {
            0x800: parse_ipv4;
            default: accept;
        }
    }
    state parse_ipv4 {
        packet.extract(hdr.ipv4);
        transition select(hdr.ipv4.protocol) {
            6: parse_tcp;
            default: accept;
        }
    }
    state parse_tcp {
        packet.extract(hdr.tcp);
        transition accept;
    }
}
 action drop() {
        mark_to_drop(standard_metadata);
    }

Step3:设计控制流

在这里它通过了一个表来指定下一跳的位置,可以看到,

  • 不再用的是ipv4_forward的action了,而是使用了set_nhop的操作
  • 这个操作根据哈希的结果指定下一条要去哪,哈希的算法在set_ecmp_select中设置
  • 根据目的地址来进行hash,hash之后目的地址就不一定是原来的了
  • 当这个包是ipv4包,而且这个包的是没有超过最大跳数的(ttl>0)就应用两个table
control MyIngress(inout headers hdr,
                  inout metadata meta,
                  inout standard_metadata_t standard_metadata) {

    action drop() {
        mark_to_drop(standard_metadata);
    }
    action set_ecmp_select(bit<16> ecmp_base, bit<32> ecmp_count) {
        /* TODO: hash on 5-tuple and save the hash result in meta.ecmp_select
           so that the ecmp_nhop table can use it to make a forwarding decision accordingly */
        hash(meta.ecmp_select,
            HashAlgorithm.crc16,
            ecmp_base,
            { hdr.ipv4.srcAddr,
              hdr.ipv4.dstAddr,
              hdr.ipv4.protocol,
              hdr.tcp.srcPort,
              hdr.tcp.dstPort },
            ecmp_count);
    }
    action set_nhop(bit<48> nhop_dmac, bit<32> nhop_ipv4, bit<9> port) {
        hdr.ethernet.dstAddr = nhop_dmac;
        hdr.ipv4.dstAddr = nhop_ipv4;
        standard_metadata.egress_spec = port;
        hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
    }
    table ecmp_group {
        key = {
            hdr.ipv4.dstAddr: lpm;
        }
        actions = {
            drop;
            set_ecmp_select;
        }
        size = 1024;
    }
    table ecmp_nhop {
        key = {
            meta.ecmp_select: exact;
        }
        actions = {
            drop;
            set_nhop;
        }
        size = 2;
    }
    apply {
        /* TODO: apply ecmp_group table and ecmp_nhop table if IPv4 header is
         * valid and TTL hasn't reached zero
         */
        if(hdr.ipv4.isValid()&&hdr.ipv4.ttl>0){
            ecmp_group.apply();
            ecmp_nhop.apply();
        }
    }
}

Step4:实验

同时开启三个终端,当我的h1 ./send.py 10.0.0.1 "lcz is coming"时,发现h2和h3都有可能会收到,说明负载被均衡了,这里可以看到,10.0.0.1并不是这里任何一个主机的地址,这个目的地址被哈希掉了成为了h2或h3地址的某一个

p4实现负载均衡_第2张图片

 我使用抓包工具验证一下,我同时开了s1-eth1 s2-eth1 s3-eth1来抓包,我发送了8个数据包,可以看到,中间抓包工具在s1-eth1抓到了8个包,目的地址是10.0.0.1,但是从它们出去以后,抵达了目的网段的时候,目的地址就是各自的h2或h3了,这是因为被哈希了

p4实现负载均衡_第3张图片

 

 小结

  • 这样的发包模式是基于哈希的,也就是发的包不是一直连续的
  • 假设一个场景(是我的毕设),有个应用要上传一段视频,这段UDP包,要分布式发往不同的服务器做应用处理最后把结果汇聚到源地址上,如果一条路径上包不连续,就没有任何意义,因为服务器根本处理不了断断续续的内容
  • 如果我想实现,一个端口发连续的30%的包,然后紧接着另一个端口发连续的50%的包,然后紧接着再来一个端口发20%的包,要怎么做?也就是按比例划分而不是概率划分
  • 我的想法是p4设置一个表,这个表执行一个匹配操作,如果包头的值在0-20%在20%-70%在70%100会分别发往不同的服务器,但是控制面的实时配置工作以及如何匹配我还不是很了解,需要再多多学习!

你可能感兴趣的:(Level.4,SDN实验,负载均衡,服务器,网络)