-
Notifications
You must be signed in to change notification settings - Fork 193
Dpctl Flow Mod Cases
Flow-mod is the most variable command of dpctl. The number of match fields, instructions and actions, always raise doubts on how to add some specific flow. So this page aims to be a reference for people starting to get used with the wide range of possibilities that flow mod brings.
We will start start with lists of all match fields, instructions and actions, because the first doubt is always: How is that field named?
## Match FieldsField name | Description |
---|---|
in_port | Switch input port |
meta | Metadata passed between tables |
eth_dst | Ethernet destination address |
eth_type | Ethernet frame type |
eth_src | Ethernet source address |
vlan_vid | VLAN id |
vlan_pcp | VLAN priority |
ip_dscp | IP DSCP |
ip_ecn | IP ECN |
ip_proto | IP protocol |
ip_src | IPv4 source address |
ip_dst | IPv4 destination address |
tcp_src | TCP source port |
tcp_dst | TCP destiny port |
udp_src | UDP source port |
udp_dst | UDP destiny port |
sctp_src | SCTP source port |
sctp_dst | SCTP destination port |
icmp_code | ICMP type |
icmp_type | ICMP code |
arp_op | ARP opcode |
arp_spa | ARP source IPv4 address |
arp_tpa | ARP target IPv4 address |
arp_sha | ARP source hardware address |
arp_tha | ARP target hardware address |
ipv6_src | IPv6 source address |
ipv6_dst | IPv6 destination address |
ipv6_flabel | IPv6 Flow Label |
icmpv6_code | ICMPv6 type |
icmpv6_type | ICMPv6 code |
ipv6_nd_target | Target address for ND |
ipv6_nd_sll | Source link-layer for ND |
ipv6_nd_tll | Target link-layer for ND |
mpls_label | MPLS label |
mpls_tc | MPLS TC |
pbb_isid | PBB I-SID |
tunn_id | Logical Port Metadata |
ext_hdr | IPv6 Extension Header pseudo-field |
Field name | Description |
---|---|
goto | Go to the next flow table |
meta | Write on the metadata field |
write | Write actions in the action set |
apply | Applies the action(s) immediately |
clear | Clear the action set |
meter | Apply meter |
Field name | Description |
---|---|
output | Output packet to a port |
ttl_out | Copy TTL from the next to outermost header to the outermost |
ttl_in | Copy TLL from the outermost header to the next to outermost |
mpls_ttl | Set MPLS TTL |
mpls_dec | Decrease MPLS TTL |
push_vlan | Push VLAN tag |
pop_vlan | Pop VLAN tag |
push_pbb | Push PBB I-TAG tag |
pop_pbb | Pop PBB I-TAG tag |
push_mpls | Push MPLS tag |
pop_mpls | Pop MPLS tag |
queue | Set queue id |
group | Apply group entry |
nw_ttl | Set IP TTL |
nw_dec | Decrement IP TTL |
set_field | Set one packet field |
The simplest flow mod is the one which matches all fields. To create this flow just omit the match fields.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none",
port="any", group="any", flags="0x0", match=oxm{all match}, insts=[apply{acts=[out{port="2"}]}]}
OK.
Inport is one of the most common fields to match. In our example we will see how easy is to establish connection between two hosts attached to the ports 1 and 2.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=1 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{in_port="1"}, insts=[apply{acts=[out{port="2"}]}]}
OK.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=2 apply:output=1
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{in_port="2"}, insts=[apply{acts=[out{port="1"}]}]}
OK.
After the addition of these flows, packets should be forwarded in both ways. Pretty easy.
#### Ethernet headerThe fields to match in the Ethernet header are the source and destination MAC and the Ethernet type. The Ethernet type is should be a very common field, as it is a pre-requisite for upper layer fields.
In the first example, we will install flows that usually installed by a learning switch application.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=1,eth_dst=00:00:00:00:00:01 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{in_port="1",eth_src=00:00:00:00:00:01, eth_dst="00:00:00:00:00:01"}, insts=[apply{acts=[out{port="2"}]}]}
OK.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=2,eth_dst=00:00:00:00:00:01 apply:output=1
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{in_port="2",eth_src=00:00:00:00:00:02, eth_dst="00:00:00:00:00:01"}, insts=[apply{acts=[out{port="1"}]}]}
OK.
In our second example, we will install a flow that will forward only IPv4 packets between two hosts, adding the ethernet type 0x800 to the match fields of our previous example.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=2,eth_type=0x800,eth_src=00:00:00:00:00:02,eth_dst=00:00:00:00:00:01 apply:output=1
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{eth_dst="00:00:00:00:00:01", in_port="2", eth_src="00:00:00:00:00:02", eth_type="0x800"}, insts=[apply{acts=[out{port="1"}]}]}
OK.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=1,eth_type=0x800,eth_src=00:00:00:00:00:01,eth_dst=00:00:00:00:00:02 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{eth_dst="00:00:00:00:00:02", in_port="1", eth_src="00:00:00:00:00:01", eth_type="0x800"}, insts=[apply{acts=[out{port="2"}]}]}
OK.
The ethernet source and destination address fields can be masked. In the example, a flow is installed to match the inport, the ethernet types just like we saw before. In addition an ethernet destination mask is specified. The flow will match packets from the port 1, with IPv4 as the ethernet type and with the destination MAC starting with 10.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=1,eth_type=0x800,eth_dst=10:11:22:33:45:55/ff:00:00:00:00:00 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{eth_dst="10:11:22:33:45:55", eth_dst_mask="ff:00:00:00:00:00", in_port="1", eth_type="0x800"}, insts=[apply{acts=[out{port="2"}]}]}
OpenFlow specifies two match field for Vlans, the vlan id and vlan priority. The first example shows how to match on Vlan fields.
unix:/tmp/ofd flow-mod cmd=add,table=0 vlan_vid=12,vlan_pcp=7 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{vlan_vid="12", vlan_pcp="7"}, insts=[apply{acts=[out{port="2"}]}]}
OK
With push and pop actions it's possible to tag and untag packets going through the switch. In our next example we will look how these actions work.
The first example pushes a vlan tag and sets the vlan id. An action that pushes a tag should have a set field action on the sequence, to set the tag identifier.
unix:/tmp/ofd flow-mod cmd=add,table=0 in_port=1,eth_dst=00:00:00:00:00:01 apply:push_vlan=0x8100,set_field=vlan_vid:110,output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{in_port="1", eth_dst="00:00:00:00:00:01"}, insts=[apply{acts=[vlan_psh{eth="0x8100"}, set_field{field:vlan_vid="110"}, out{port="2"}]}]}
OK.
The second example install a flow to pop the tag pushed in the example above.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 vlan_vid=110 apply:pop_vlan,output=3
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{vlan_vid="110"}, insts=[apply{acts=[vlan_pop, out{port="3"}]}]}
OK.
Dpctl can install flows with the MPLS label and TC fields. The first examples shows a flow with both field in the match. To match MPLS fields the ethertype should be present with a value of 0x8847 or 0x8848, if that field is not present the switch returns a bad pre-requisite error.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 eth_type=0x8847,mpls_label=17,mpls_tc=3 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{mpls_label="17", mpls_tc="3", eth_type="0x8847"}, insts=[apply{acts=[out{port="2"}]}]}
OK.
Similar to VLAN, mpls tags can be pushed and popped from the packet using actions. The second example shows a flow with a push action. Again, a set_field action is needed to set the MPLS label, because the action don't do it.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 eth_type=0x8847 apply:push_mpls=0x8847,set_field=mpls_label:12,output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{eth_type="0x8847"}, insts=[apply{acts=[mpls_psh{eth="0x8847"}, set_field{field:mpls_label="12"}, out{port="2"}]}]}
OK.
In the last example, a flow with a pop mpls label action is installed.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 eth_type=0x8847,mpls_label=12 apply:pop_mpls=0x8847,output=1
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{mpls_label="12", eth_type="0x8847"}, insts=[apply{acts=[mpls_pop{eth="0x8847"}, out{port="1"}]}]}
OK.
OpenFlow 1.3 allows flows to match the service identifier (I-SID) of the first PBB tag. In our example, we will show how to match this field and how to create a PBB packet with the I-TAG and the B-TAG, which are inserted using the push_pbb action and push_vlan action, with the ethernet type equals to 0x88A8.
dpctl unix:/tmp/ofd flow-mod table=0,cmd=add in_port=1 apply:push_pbb=0x0x88E7,set_field=pbb_isid:34,push_vlan=0x88A8,set_field=vlan_vid:12,output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{in_port="1"}, insts=[apply{acts=[pbb_psh{eth="0x88e7"}, set_field{field:pbb_isid="34"}, vlan_psh{eth="0x88A8"}, set_field{field:vlan_vid="12"}, out{port="2"}]}]}
OK.
OpenFlow supports ARP source and target IP addresses, the source and target ethernet addresses and the Opcode.
In the example, the flow have all ARP possible fields.
dpctl unix:/tmp/ofd flow-mod table=0,cmd=add eth_type=0x806,arp_sha=00:00:00:00:00:01,arp_tha=00:00:00:00:00:02,arp_spa=192.168.0.1,arp_tpa=192.168.0.2,arp_op=1 apply:output=3
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{arp_op="0x1", arp_spa="192.168.0.1", arp_tha="00:00:00:00:00:02", arp_sha="00:00:00:00:00:01", arp_tpa="192.168.0.2", eth_type="0x806"}, insts=[apply{acts=[out{port="3"}]}]}
OK.
There are five fields to match in the IPv4 header. Beyond the source and destination address it's possible to match the ip proto and the ecn and dscp fields which belongs to the IP TOS. The pre-requisite to match is the ethernet type equals to 0x800.
Our first example shows a flow with IP source and destination addresses. The destination is masked by the network mask /24, which means we want to match only in the first eight bytes of the address. The actions will decrease the ip ttl and output the packet to the port 3.
dpctl unix:/tmp/ofd flow-mod cmd=add,table=0 eth_type=0x800,ip_src=192.168.0.1,ip_dst=172.40.56.101/24 apply:nw_dec,output=3
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{ipv4_src="192.168.0.1", ipv4_dst="172.40.56.101", ipv4_dst_mask="255.255.255.0", eth_type="0x800"}, insts=[apply{acts=[nw_dec, out{port="3"}]}]}
OK.
OpenFlow 1.2 brought IPv6 to the light with the possibility to match the source and destination addresses and the flow label. Also, ICMPv6 and the Neighbor Discovery Protocols were added to the specification, and will be covered in next topics.
The example shows a flow with IPv6 source and destination addresses. The destination address has network mask /48.
dpctl unix:/tmp/ofd flow-mod table=0,cmd=add eth_type=0x86dd,ipv6_src=2001:0db8:85a3:0042:0000:8a2e:0370:7334,ipv6_dst=2001:0002:6c::430/48 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{nw_dst_ipv6="2001:2:6c::430", nw_dst_ipv6_mask="ffff:ffff:ffff::", eth_type="0x86dd", nw_src_ipv6="2001:db8:85a3:42:0:8a2e:370:7334"}, insts=[apply{acts=[out{port="2"}]}]}
OK.
OpenFlow supports UDP and TCP source and destination ports. Due to the similarity of flows containing these fields, we are covering both in just one topic.
To install a rule with UDP source and destination,you should have the field ip_proto equals to 17.
dpctl unix:/tmp/ofd flow-mod table=0,cmd=add eth_type=0x800,ip_proto=17,udp_src=36,udp_dst=1200 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{udp_src="36", ip_proto="17", udp_dst="1200", eth_type="0x800"}, insts=[apply{acts=[out{port="2"}]}]}
OK.
Similarly to UDP, TCP rules need a ip proto field with a value of 6.
dpctl unix:/tmp/ofd flow-mod table=0,cmd=add eth_type=0x800,ip_proto=6,tcp_src=36,tcp_dst=1200 apply:output=2
SENDING:
flow_mod{table="0", cmd="add", cookie="0x0", mask="0x0", idle="0", hard="0", prio="32768", buf="none", port="any", group="any", flags="0x0", match=oxm{tcp_src="36", ip_proto="6", tcp_dst="1200", eth_type="0x800"}, insts=[apply{acts=[out{port="2"}]}]}
OK.