intrig-unicamp / mininet-wifi

Emulator for Software-Defined Wireless Networks
https://mn-wifi.readthedocs.io/
Other
431 stars 239 forks source link

Combination of Mesh Wi-Fi and P4 access point(AP) #518

Closed davidchen0970 closed 5 months ago

davidchen0970 commented 6 months ago

Hi, I tried to create a topology using mesh Wi-Fi and P4 AP, but it failed to pass the ping test at all during the test. After opening the Wireshark program, I found that the source MAC address and destination MAC address will become the same in ping test.

The topology and P4 code are as follows:

basic.p4

/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>

const bit<16> TYPE_IPV4 = 0x800;

/*************************************************************************
*********************** H E A D E R S  ***********************************
*************************************************************************/

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<8>    diffserv;
    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 {
    /* empty */
}

struct headers {
    ethernet_t   ethernet;
    ipv4_t       ipv4;
}

/*************************************************************************
*********************** P A R S E R  ***********************************
*************************************************************************/

parser MyParser(packet_in packet,
                out headers hdr,
                inout metadata meta,
                inout standard_metadata_t standard_metadata) {

    state start {

        packet.extract(hdr.ethernet);
        transition select(hdr.ethernet.etherType){

            TYPE_IPV4: ipv4;
            default: accept;

        }

    }

    state ipv4 {

        packet.extract(hdr.ipv4);
        transition accept;
    }

}

/*************************************************************************
************   C H E C K S U M    V E R I F I C A T I O N   *************
*************************************************************************/

control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
    apply {  }
}

/*************************************************************************
**************  I N G R E S S   P R O C E S S I N G   *******************
*************************************************************************/

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) {

        //set the src mac address as the previous dst, this is not correct right?
        hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;

       //set the destination mac address that we got from the match in the table
        hdr.ethernet.dstAddr = dstAddr;

        //set the output port that we also get from the table
        standard_metadata.egress_spec = port;

        //decrease ttl by 1
        hdr.ipv4.ttl = hdr.ipv4.ttl -1;

    }

    table ipv4_lpm {
        key = {
            hdr.ipv4.dstAddr: exact;
        }
        actions = {
            ipv4_forward;
            drop;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }

    apply {

        //only if IPV4 the rule is applied. Therefore other packets will not be forwarded.
        if (hdr.ipv4.isValid()){
            ipv4_lpm.apply();

        }
    }
}

/*************************************************************************
****************  E G R E S S   P R O C E S S I N G   *******************
*************************************************************************/

control MyEgress(inout headers hdr,
                 inout metadata meta,
                 inout standard_metadata_t standard_metadata) {
    apply {  }
}

/*************************************************************************
*************   C H E C K S U M    C O M P U T A T I O N   **************
*************************************************************************/

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.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);
    }
}

/*************************************************************************
***********************  D E P A R S E R  *******************************
*************************************************************************/

control MyDeparser(packet_out packet, in headers hdr) {
    apply {

        //parsed headers have to be added again into the packet.
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);

    }
}

/*************************************************************************
***********************  S W I T C H  *******************************
*************************************************************************/

//switch architecture
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;

commands_ap1.txt

table_set_default ipv4_lpm drop
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.1 => 00:00:00:00:00:01 3
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.2 => 00:00:00:00:00:02 1
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.3 => 00:00:00:00:00:03 2
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.4 => 00:00:00:00:00:04 1

commands_ap2.txt

table_set_default ipv4_lpm drop
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.1 => 00:00:00:00:00:01 1
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.2 => 00:00:00:00:00:02 3
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.3 => 00:00:00:00:00:03 1
table_add MyIngress.ipv4_lpm ipv4_forward 10.0.0.4 => 00:00:00:00:00:04 2

p4.py

import os
import sys

from mininet.log import setLogLevel, info
from mn_wifi.cli import CLI
from mn_wifi.net import Mininet_wifi
from mn_wifi.bmv2 import P4AP, P4Host
from mininet.node import RemoteController, Controller
import time
from mn_wifi.link import wmediumd, mesh

def topology(remote_controller):

    net = Mininet_wifi()
    h1 = net.addHost('h1', ip='10.0.0.1', cls=P4Host, mac="00:00:00:00:00:01")
    h2 = net.addHost('h2', ip='10.0.0.2', cls=P4Host, mac="00:00:00:00:00:02")
    sta1 = net.addStation('sta1', ip='10.0.0.3', mac="00:00:00:00:00:03", position='100,50,0')
    sta2 = net.addStation('sta2', ip='10.0.0.4', mac="00:00:00:00:00:04", position='300,50,0')

    args1 = dict()
    args2 = dict()
    if not remote_controller:
        path = os.path.dirname(os.path.abspath(__file__))
        json_file = path + '/ap-runtime.json'
        config1 = path + '/commands_ap1.txt'
        config2 = path + '/commands_ap2.txt'
        args1 = {'json': json_file, 'switch_config': config1}
        args2 = {'json': json_file, 'switch_config': config2}

    ap1 = net.addAccessPoint('ap1', cls=P4AP, netcfg=True, ssid='ssid1', position='100,100,0', dpid='1', wlans=2, **args1)
    ap2 = net.addAccessPoint('ap2', cls=P4AP, netcfg=True, ssid='ssid2', position='300,100,0', dpid='2', wlans=2, **args2)

    if remote_controller:
        info('*** Adding Controller\n')
        net.addController('c0', controller=RemoteController)

    info("*** Configuring propagation model\n")
    net.setPropagationModel(model="logDistance", exp=4)

    net.configureWifiNodes()

    net.addLink(sta1, ap1)
    net.addLink(sta2, ap2)
    net.addLink(h1, ap1)
    net.addLink(h2, ap2)
    net.addLink(ap1, intf='ap1-wlan2', cls=mesh, ssid='mesh-ssid', channel=5)
    net.addLink(ap2, intf='ap2-wlan2', cls=mesh, ssid='mesh-ssid', channel=5)

    info('*** Plotting Graph\n')
    net.plotGraph(max_x=500, max_y=500)

    net.start()
    if not remote_controller:
        net.staticArp()

    CLI(net)

    net.stop()

if __name__ == '__main__':
    setLogLevel('info')
    remote_controller = True if '-r' in sys.argv else False
    topology(remote_controller)

螢幕擷取畫面 2023-12-25 035936 螢幕擷取畫面 2023-12-25 040154

The virtual environment uses the virtual machine provided by the official GitHub.

Thanks!!