Sending strings via P4 rules

Hello, I want to transfer some data from one P4 switch to the other. For doing so, I want to insert a string, for example, “Hello” in the packet header. I am wondering if it is possible to send strings via rules to the switch.

Hi,

Processing strings as part of packets is complicated. Strings tend to be of different size and if you want to send strings with the same size (for instance, 5 characters) then it is easier. If you want to send a string as part of a packet you should think of the ASCII character encoding. If you remember the typical ASCII table, you get a numerical representation for each character. See here.

Now, you ask:

to insert a string (…) in the packet header

We can do that by creating a new header:

//Header definition
header message_t {
    bit<40> str;
}

struct headers {
    ethernet_t   ethernet;
    ipv4_t       ipv4;
    message_t    message;
}

//Deparser

apply {
    packet.emit(hdr.ethernet);
    packet.emit(hdr.ipv4);
    packet.emit(hdr.message);
}

Your string will be of 5 characters, because each character occupies 8 bits, so 8 x 5 = 40 bits. You can always have less characters but you need to pad the str field.

You also wonder…

if it is possible to send strings via rules to the switch.

So, if you want to do that, you will need a table with some matching criteria and an action that sets your header as valid and assigns the value yo want (the string). See, I came up with this idea:

action add_string(bit<40> myString) {
    hdr.message.setValid();
    hdr.message.str = myString;
}

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

apply {
    if (hdr.ipv4.isValid()) {
        addString_exact.apply();
        ipv4_lpm.apply();
    }
}

I added this lines to the basic exercise from P4 tutorials, in case you need further information. Now, you need a rule like this:

{
  "table": "MyIngress.addString_exact",
  "match": {
    "hdr.ipv4.dstAddr": "10.0.2.2"
  },
  "action_name": "MyIngress.add_string",
  "action_params": {
    "myString": 495556125032
  }
}

495556125032 is the same as “sarah” or 0x7361726168.

Now, be aware that this is a naive approach and the IPv4 checksum or will fail (unless you compute it again). In the following capture, I inserted your string between IPv4 and ICMP, so the Wireshark dissector think this is an incorrect or unknown type of ICMP packet. Also, the checksum seems to be wrong, as mentioned before. But you can still read “sarah”.

To add a little information, consider that processing strings in the data plane or text-based protocols (and many application layer protocols) is tricky. String or application layer data tend to be of variable size. Handling variable size in P4 is possible with varbit fields, but the available operations is limited last time I checked [p4-guide]. I don’t mean that processing application layer data is impossible because you can still find a few use cases (Woodruff or Jensen to name a couple, but there are more).

Hope it helps,