diff mbox

[ovs-dev,1/3] tunnel: Add support to configure ptk_mark

Message ID 1482918254-3915-2-git-send-email-pshelar@ovn.org
State Superseded
Headers show

Commit Message

Pravin Shelar Dec. 28, 2016, 9:44 a.m. UTC
Today packet mark action is broaken for Tunnel ports with
tunnel monitoring. User can write a flow to set pkt-mark for
any tunnel packet generated by vswitchd itself, like BFD packets.

Following patch introduces new option in OVSDB tunnel
configuration so that user can set skb-mark for given
tunnel endpoint. OVS would set the mark according to the
skb-mark option for all tunnel traffic including packets
generated by vSwitchd like tunnel monitoring BFD packet.

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
---
 lib/netdev-vport.c       |  8 ++++++++
 lib/netdev.h             |  1 +
 ofproto/tunnel.c         |  5 +++++
 tests/tunnel-push-pop.at | 16 ++++++++++++++++
 vswitchd/vswitch.xml     |  4 ++++
 5 files changed, 34 insertions(+)

Comments

Jarno Rajahalme Jan. 23, 2017, 5:04 p.m. UTC | #1
Pravin,

Sorry for the delay, I hope you find time to respond.

> On Dec 28, 2016, at 1:44 AM, Pravin B Shelar <pshelar@ovn.org> wrote:
> 
> Today packet mark action is broaken for Tunnel ports with
> tunnel monitoring.

“broaken”->”broken”

Could you be more specific here. Setting packet mark works, but apparently not when sending the packet to a tunnel, or possibly when sending packet to a tunnel when tunnel monitoring (you mean BFD?). What exactly is the problem?

> User can write a flow to set pkt-mark for
> any tunnel packet generated by vswitchd itself, like BFD packets.
> 

So the problem is that if a flow sets the pkt_mark, it will be also used for BFD packets? Or is it that it will not be used for BFD packets? What is the desired behavior?

> Following patch introduces new option in OVSDB tunnel
> configuration so that user can set skb-mark for given
> tunnel endpoint. OVS would set the mark according to the
> skb-mark option for all tunnel traffic including packets
> generated by vSwitchd like tunnel monitoring BFD packet.
> 

What happens to the tunnel packet mark when the new option is not specified? Is that behavior changed?

> Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
> ---
> lib/netdev-vport.c       |  8 ++++++++
> lib/netdev.h             |  1 +
> ofproto/tunnel.c         |  5 +++++
> tests/tunnel-push-pop.at | 16 ++++++++++++++++
> vswitchd/vswitch.xml     |  4 ++++
> 5 files changed, 34 insertions(+)
> 
> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
> index 02a246a..25dd0e8 100644
> --- a/lib/netdev-vport.c
> +++ b/lib/netdev-vport.c
> @@ -505,6 +505,10 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
>             }
> 
>             free(str);
> +        } else if (!strcmp(node->key, "egress_pkt_mark")) {
> +            char *ptr = NULL;
> +
> +            tnl_cfg.egress_pkt_mark = strtoul(node->value, &ptr, 10);

Could skip the “ptr” and use NULL instead.

Should document somewhere what happens when the option is not given, which seems to be the same as setting the egress_pkt_mark to zero.

>         } else {
>             VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->key);
>         }
> @@ -623,6 +627,10 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
>         smap_add(args, "df_default", "false");
>     }
> 
> +    if (tnl_cfg.egress_pkt_mark) {
> +        smap_add_format(args, "egress_pkt_mark",
> +                        "%"PRIu32, tnl_cfg.egress_pkt_mark);
> +    }


Does a zero mark mean that the mark is not used? If the zero value is still used is leaving it out misleading?

>     return 0;
> }
> 
> diff --git a/lib/netdev.h b/lib/netdev.h
> index a667fe3..5ec1274 100644
> --- a/lib/netdev.h
> +++ b/lib/netdev.h
> @@ -89,6 +89,7 @@ struct netdev_tunnel_config {
>     struct in6_addr ipv6_dst;
> 
>     uint32_t exts;
> +    uint32_t egress_pkt_mark;
> 
>     uint8_t ttl;
>     bool ttl_inherit;
> diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
> index ce727f4..6205948 100644
> --- a/ofproto/tunnel.c
> +++ b/ofproto/tunnel.c
> @@ -461,6 +461,11 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow,
>         | (cfg->csum ? FLOW_TNL_F_CSUM : 0)
>         | (cfg->out_key_present ? FLOW_TNL_F_KEY : 0);
> 
> +    if (cfg->egress_pkt_mark) {
> +        flow->pkt_mark = cfg->egress_pkt_mark;
> +        wc->masks.pkt_mark = UINT32_MAX;

Here the pkt_mark from the flow is not used or inherited, so why are we setting the mask (which causes an exact match on the incoming pkt_mark value (which is likely zero))?

> +    }
> +

If egress_pkt_mark is zero, do we further on in the tunnel code (maybe due to later patches) use the pkt_mask value from the flow?

>     if (pre_flow_str) {
>         char *post_flow_str = flow_to_string(flow);
>         char *tnl_str = tnl_port_fmt(tnl_port);
> diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
> index 700ef55..4aaa669 100644
> --- a/tests/tunnel-push-pop.at
> +++ b/tests/tunnel-push-pop.at
> @@ -12,6 +12,8 @@ AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=vxlan \
>                        options:remote_ip=1.1.2.93 options:out_key=flow options:csum=true ofport_request=4\
>                     -- add-port int-br t4 -- set Interface t4 type=geneve \
>                        options:remote_ip=flow options:key=123 ofport_request=5\
> +                    -- add-port int-br t5 -- set Interface t5 type=geneve \
> +                       options:remote_ip=1.1.2.93 options:out_key=flow options:egress_pkt_mark=1234 ofport_request=6\
>                        ], [0])
> 
> AT_CHECK([ovs-appctl dpif/show], [0], [dnl
> @@ -25,6 +27,7 @@ dummy@ovs-dummy: hit:0 missed:0
> 		t2 2/4789: (vxlan: key=123, remote_ip=1.1.2.92)
> 		t3 4/4789: (vxlan: csum=true, out_key=flow, remote_ip=1.1.2.93)
> 		t4 5/6081: (geneve: key=123, remote_ip=flow)
> +		t5 6/6081: (geneve: egress_pkt_mark=1234, out_key=flow, remote_ip=1.1.2.93)
> ])
> 
> dnl First setup dummy interface IP address, then add the route
> @@ -91,6 +94,12 @@ AT_CHECK([tail -1 stdout], [0],
>   [Datapath actions: tnl_pop(6081)
> ])
> 
> +dnl Check Geneve tunnel (t6) pop
> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.2.96,dst=1.1.2.88,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=6081)'], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: tnl_pop(6081)
> +])
> +
> dnl Check VXLAN tunnel push
> AT_CHECK([ovs-ofctl add-flow int-br action=2])
> AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
> @@ -119,6 +128,13 @@ AT_CHECK([tail -1 stdout], [0],
>   [Datapath actions: tnl_push(tnl_port(6081),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100))
> ])
> 
> +dnl Check Geneve tunnel push with pkt-mark
> +AT_CHECK([ovs-ofctl add-flow int-br "actions=set_tunnel:234,6"])
> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: set(skb_mark(0x4d2)),tnl_push(tnl_port(6081),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b7,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.93,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(vni=0xea)),out_port(100))
> +])
> +
> dnl Check Geneve tunnel push with options
> AT_CHECK([ovs-ofctl add-tlv-map int-br "{class=0xffff,type=0x80,len=4}->tun_metadata0"])
> AT_CHECK([ovs-ofctl add-flow int-br "actions=set_field:1.1.2.92->tun_dst,set_field:0xa->tun_metadata0,5"])
> diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> index b4af5a5..3ec8193 100644
> --- a/vswitchd/vswitch.xml
> +++ b/vswitchd/vswitch.xml
> @@ -2226,6 +2226,10 @@
>         to <code>false</code> to disable.
>       </column>
> 
> +      <column name="options" key="egress_pkt_mark">
> +        Optional.  The pkt_mark to be set on the encapsulating packet.
> +      </column>
> +

We should document the behavior in the absence of this option as well.

>       <group title="Tunnel Options: vxlan only">
> 
>         <column name="options" key="exts">
> -- 
> 2.9.3
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Pravin Shelar Jan. 24, 2017, 8:23 p.m. UTC | #2
On Mon, Jan 23, 2017 at 9:04 AM, Jarno Rajahalme <jarno@ovn.org> wrote:
> Pravin,
>
> Sorry for the delay, I hope you find time to respond.
>
>> On Dec 28, 2016, at 1:44 AM, Pravin B Shelar <pshelar@ovn.org> wrote:
>>
>> Today packet mark action is broaken for Tunnel ports with
>> tunnel monitoring.
>
> “broaken”->”broken”
>
ok.

> Could you be more specific here. Setting packet mark works, but apparently not when sending the packet to a tunnel, or possibly when sending packet to a tunnel when tunnel monitoring (you mean BFD?). What exactly is the problem?
>
>> User can write a flow to set pkt-mark for
>> any tunnel packet generated by vswitchd itself, like BFD packets.
>>
>
> So the problem is that if a flow sets the pkt_mark, it will be also used for BFD packets? Or is it that it will not be used for BFD packets? What is the desired behavior?
>
Problem is for tunnels with tunnel monitoring. Using OVS flow table we
can set pkt-mark for tunnel packets in datapath, but not for tunnel
monitoring packets which are originated from vswitchd.

>> Following patch introduces new option in OVSDB tunnel
>> configuration so that user can set skb-mark for given
>> tunnel endpoint. OVS would set the mark according to the
>> skb-mark option for all tunnel traffic including packets
>> generated by vSwitchd like tunnel monitoring BFD packet.
>>
>
> What happens to the tunnel packet mark when the new option is not specified? Is that behavior changed?
>
Nope, it remains the same. As mentioned in the man page it is optional
parameter.

>> Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
>> ---
>> lib/netdev-vport.c       |  8 ++++++++
>> lib/netdev.h             |  1 +
>> ofproto/tunnel.c         |  5 +++++
>> tests/tunnel-push-pop.at | 16 ++++++++++++++++
>> vswitchd/vswitch.xml     |  4 ++++
>> 5 files changed, 34 insertions(+)
>>
>> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
>> index 02a246a..25dd0e8 100644
>> --- a/lib/netdev-vport.c
>> +++ b/lib/netdev-vport.c
>> @@ -505,6 +505,10 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
>>             }
>>
>>             free(str);
>> +        } else if (!strcmp(node->key, "egress_pkt_mark")) {
>> +            char *ptr = NULL;
>> +
>> +            tnl_cfg.egress_pkt_mark = strtoul(node->value, &ptr, 10);
>
> Could skip the “ptr” and use NULL instead.
>
ok.

> Should document somewhere what happens when the option is not given, which seems to be the same as setting the egress_pkt_mark to zero.
>
>>         } else {
>>             VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->key);
>>         }
>> @@ -623,6 +627,10 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
>>         smap_add(args, "df_default", "false");
>>     }
>>
>> +    if (tnl_cfg.egress_pkt_mark) {
>> +        smap_add_format(args, "egress_pkt_mark",
>> +                        "%"PRIu32, tnl_cfg.egress_pkt_mark);
>> +    }
>
>
> Does a zero mark mean that the mark is not used? If the zero value is still used is leaving it out misleading?
>
This is good point. If user explicitly sets the mark then we need to
reset it, I will update the patch.

>>     return 0;
>> }
>>
>> diff --git a/lib/netdev.h b/lib/netdev.h
>> index a667fe3..5ec1274 100644
>> --- a/lib/netdev.h
>> +++ b/lib/netdev.h
>> @@ -89,6 +89,7 @@ struct netdev_tunnel_config {
>>     struct in6_addr ipv6_dst;
>>
>>     uint32_t exts;
>> +    uint32_t egress_pkt_mark;
>>
>>     uint8_t ttl;
>>     bool ttl_inherit;
>> diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
>> index ce727f4..6205948 100644
>> --- a/ofproto/tunnel.c
>> +++ b/ofproto/tunnel.c
>> @@ -461,6 +461,11 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow,
>>         | (cfg->csum ? FLOW_TNL_F_CSUM : 0)
>>         | (cfg->out_key_present ? FLOW_TNL_F_KEY : 0);
>>
>> +    if (cfg->egress_pkt_mark) {
>> +        flow->pkt_mark = cfg->egress_pkt_mark;
>> +        wc->masks.pkt_mark = UINT32_MAX;
>
> Here the pkt_mark from the flow is not used or inherited, so why are we setting the mask (which causes an exact match on the incoming pkt_mark value (which is likely zero))?
>
The problem is in commit odp action. If I do not set the mask then the
odp action uses zero mask and key to generate skb-mark set action.
Result is pkt-mark is always zero in set pkt-mark action.


>> +    }
>> +
>
> If egress_pkt_mark is zero, do we further on in the tunnel code (maybe due to later patches) use the pkt_mask value from the flow?
>
If egress_pkt_mark is set then it would overwrite the flow packet mark.

>>     if (pre_flow_str) {
>>         char *post_flow_str = flow_to_string(flow);
>>         char *tnl_str = tnl_port_fmt(tnl_port);
>> diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
>> index 700ef55..4aaa669 100644
>> --- a/tests/tunnel-push-pop.at
>> +++ b/tests/tunnel-push-pop.at
>> @@ -12,6 +12,8 @@ AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=vxlan \
>>                        options:remote_ip=1.1.2.93 options:out_key=flow options:csum=true ofport_request=4\
>>                     -- add-port int-br t4 -- set Interface t4 type=geneve \
>>                        options:remote_ip=flow options:key=123 ofport_request=5\
>> +                    -- add-port int-br t5 -- set Interface t5 type=geneve \
>> +                       options:remote_ip=1.1.2.93 options:out_key=flow options:egress_pkt_mark=1234 ofport_request=6\
>>                        ], [0])
>>
>> AT_CHECK([ovs-appctl dpif/show], [0], [dnl
>> @@ -25,6 +27,7 @@ dummy@ovs-dummy: hit:0 missed:0
>>               t2 2/4789: (vxlan: key=123, remote_ip=1.1.2.92)
>>               t3 4/4789: (vxlan: csum=true, out_key=flow, remote_ip=1.1.2.93)
>>               t4 5/6081: (geneve: key=123, remote_ip=flow)
>> +             t5 6/6081: (geneve: egress_pkt_mark=1234, out_key=flow, remote_ip=1.1.2.93)
>> ])
>>
>> dnl First setup dummy interface IP address, then add the route
>> @@ -91,6 +94,12 @@ AT_CHECK([tail -1 stdout], [0],
>>   [Datapath actions: tnl_pop(6081)
>> ])
>>
>> +dnl Check Geneve tunnel (t6) pop
>> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.2.96,dst=1.1.2.88,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=6081)'], [0], [stdout])
>> +AT_CHECK([tail -1 stdout], [0],
>> +  [Datapath actions: tnl_pop(6081)
>> +])
>> +
>> dnl Check VXLAN tunnel push
>> AT_CHECK([ovs-ofctl add-flow int-br action=2])
>> AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
>> @@ -119,6 +128,13 @@ AT_CHECK([tail -1 stdout], [0],
>>   [Datapath actions: tnl_push(tnl_port(6081),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100))
>> ])
>>
>> +dnl Check Geneve tunnel push with pkt-mark
>> +AT_CHECK([ovs-ofctl add-flow int-br "actions=set_tunnel:234,6"])
>> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
>> +AT_CHECK([tail -1 stdout], [0],
>> +  [Datapath actions: set(skb_mark(0x4d2)),tnl_push(tnl_port(6081),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b7,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.93,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(vni=0xea)),out_port(100))
>> +])
>> +
>> dnl Check Geneve tunnel push with options
>> AT_CHECK([ovs-ofctl add-tlv-map int-br "{class=0xffff,type=0x80,len=4}->tun_metadata0"])
>> AT_CHECK([ovs-ofctl add-flow int-br "actions=set_field:1.1.2.92->tun_dst,set_field:0xa->tun_metadata0,5"])
>> diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
>> index b4af5a5..3ec8193 100644
>> --- a/vswitchd/vswitch.xml
>> +++ b/vswitchd/vswitch.xml
>> @@ -2226,6 +2226,10 @@
>>         to <code>false</code> to disable.
>>       </column>
>>
>> +      <column name="options" key="egress_pkt_mark">
>> +        Optional.  The pkt_mark to be set on the encapsulating packet.
>> +      </column>
>> +
>
> We should document the behavior in the absence of this option as well.
>
ok.

>>       <group title="Tunnel Options: vxlan only">
>>
>>         <column name="options" key="exts">
>> --
>> 2.9.3
>>
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
diff mbox

Patch

diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 02a246a..25dd0e8 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -505,6 +505,10 @@  set_tunnel_config(struct netdev *dev_, const struct smap *args)
             }
 
             free(str);
+        } else if (!strcmp(node->key, "egress_pkt_mark")) {
+            char *ptr = NULL;
+
+            tnl_cfg.egress_pkt_mark = strtoul(node->value, &ptr, 10);
         } else {
             VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->key);
         }
@@ -623,6 +627,10 @@  get_tunnel_config(const struct netdev *dev, struct smap *args)
         smap_add(args, "df_default", "false");
     }
 
+    if (tnl_cfg.egress_pkt_mark) {
+        smap_add_format(args, "egress_pkt_mark",
+                        "%"PRIu32, tnl_cfg.egress_pkt_mark);
+    }
     return 0;
 }
 
diff --git a/lib/netdev.h b/lib/netdev.h
index a667fe3..5ec1274 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -89,6 +89,7 @@  struct netdev_tunnel_config {
     struct in6_addr ipv6_dst;
 
     uint32_t exts;
+    uint32_t egress_pkt_mark;
 
     uint8_t ttl;
     bool ttl_inherit;
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index ce727f4..6205948 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -461,6 +461,11 @@  tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow,
         | (cfg->csum ? FLOW_TNL_F_CSUM : 0)
         | (cfg->out_key_present ? FLOW_TNL_F_KEY : 0);
 
+    if (cfg->egress_pkt_mark) {
+        flow->pkt_mark = cfg->egress_pkt_mark;
+        wc->masks.pkt_mark = UINT32_MAX;
+    }
+
     if (pre_flow_str) {
         char *post_flow_str = flow_to_string(flow);
         char *tnl_str = tnl_port_fmt(tnl_port);
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index 700ef55..4aaa669 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -12,6 +12,8 @@  AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=vxlan \
                        options:remote_ip=1.1.2.93 options:out_key=flow options:csum=true ofport_request=4\
                     -- add-port int-br t4 -- set Interface t4 type=geneve \
                        options:remote_ip=flow options:key=123 ofport_request=5\
+                    -- add-port int-br t5 -- set Interface t5 type=geneve \
+                       options:remote_ip=1.1.2.93 options:out_key=flow options:egress_pkt_mark=1234 ofport_request=6\
                        ], [0])
 
 AT_CHECK([ovs-appctl dpif/show], [0], [dnl
@@ -25,6 +27,7 @@  dummy@ovs-dummy: hit:0 missed:0
 		t2 2/4789: (vxlan: key=123, remote_ip=1.1.2.92)
 		t3 4/4789: (vxlan: csum=true, out_key=flow, remote_ip=1.1.2.93)
 		t4 5/6081: (geneve: key=123, remote_ip=flow)
+		t5 6/6081: (geneve: egress_pkt_mark=1234, out_key=flow, remote_ip=1.1.2.93)
 ])
 
 dnl First setup dummy interface IP address, then add the route
@@ -91,6 +94,12 @@  AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: tnl_pop(6081)
 ])
 
+dnl Check Geneve tunnel (t6) pop
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.2.96,dst=1.1.2.88,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=6081)'], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: tnl_pop(6081)
+])
+
 dnl Check VXLAN tunnel push
 AT_CHECK([ovs-ofctl add-flow int-br action=2])
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
@@ -119,6 +128,13 @@  AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: tnl_push(tnl_port(6081),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100))
 ])
 
+dnl Check Geneve tunnel push with pkt-mark
+AT_CHECK([ovs-ofctl add-flow int-br "actions=set_tunnel:234,6"])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: set(skb_mark(0x4d2)),tnl_push(tnl_port(6081),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b7,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.93,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(vni=0xea)),out_port(100))
+])
+
 dnl Check Geneve tunnel push with options
 AT_CHECK([ovs-ofctl add-tlv-map int-br "{class=0xffff,type=0x80,len=4}->tun_metadata0"])
 AT_CHECK([ovs-ofctl add-flow int-br "actions=set_field:1.1.2.92->tun_dst,set_field:0xa->tun_metadata0,5"])
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index b4af5a5..3ec8193 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2226,6 +2226,10 @@ 
         to <code>false</code> to disable.
       </column>
 
+      <column name="options" key="egress_pkt_mark">
+        Optional.  The pkt_mark to be set on the encapsulating packet.
+      </column>
+
       <group title="Tunnel Options: vxlan only">
 
         <column name="options" key="exts">