Skip to content

Dpctl Flow Mod Cases

Eder Leão Fernandes edited this page Sep 8, 2018 · 12 revisions

Contents

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 Fields

Field 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

Instructions

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

Actions

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

Flow Mod Cases

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

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 header

The 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"}]}]}

VLAN

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.

MPLS

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. 

PBB

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.

ARP

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.

IPv4 header

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.

IPv6 header

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.

UDP and TCP

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.