A similar patch has been discussed previously: http://openvswitch.org/pipermail/dev/2010-October/004153.html Have you looked at it?
Regards, -- Romain Lenglet ----- Original Message ----- > From: "Rich Lane" <rich.l...@bigswitch.com> > To: dev@openvswitch.org > Cc: "Rich Lane" <rich.l...@bigswitch.com> > Sent: Monday, December 10, 2012 5:16:39 PM > Subject: [ovs-dev] [PATCH] support NXAST_SET_TUNNEL_DST action > > This action allows the controller to change the destination IP of the > encapsulating packet. It just exposes the existing Linux datapath > functionality. > > Tested by installing a flow with the new action and an output action > to a GRE > tunnel port. The resulting packet had the correct destination IP. > > Signed-off-by: Rich Lane <rich.l...@bigswitch.com> > --- > I would have liked to put this in under the BSN vendor ID but there > isn't any > existing support for actions from other vendors. Let me know if you'd > like me > to add that. > > I wasn't sure how to populate the tun_flags, ipv4_tos, and ipv4_ttl > fields of > the struct ovs_key_ipv4_tunnel. Would you rather the new OpenFlow > action set > all of them at once instead of just the destination IP? > > include/openflow/nicira-ext.h | 14 ++++++++++++++ > lib/odp-util.c | 29 +++++++++++++++++++++++++++++ > lib/ofp-actions.c | 25 +++++++++++++++++++++++++ > lib/ofp-actions.h | 9 +++++++++ > lib/ofp-parse.c | 5 +++++ > lib/ofp-util.def | 1 + > ofproto/ofproto-dpif.c | 4 ++++ > tests/ofp-actions.at | 3 +++ > tests/ofproto-dpif.at | 19 +++++++++++++++++++ > tests/ovs-ofctl.at | 2 ++ > 10 files changed, 111 insertions(+) > > diff --git a/include/openflow/nicira-ext.h > b/include/openflow/nicira-ext.h > index 91c96b3..a82df9c 100644 > --- a/include/openflow/nicira-ext.h > +++ b/include/openflow/nicira-ext.h > @@ -304,6 +304,7 @@ enum nx_action_subtype { > NXAST_CONTROLLER, /* struct nx_action_controller */ > NXAST_DEC_TTL_CNT_IDS, /* struct nx_action_cnt_ids */ > NXAST_WRITE_METADATA, /* struct nx_action_write_metadata > */ > + NXAST_SET_TUNNEL_DST, /* struct nx_action_set_tunnel_dst > */ > }; > > /* Header for Nicira-defined actions. */ > @@ -2212,4 +2213,17 @@ struct nx_action_write_metadata { > }; > OFP_ASSERT(sizeof(struct nx_action_write_metadata) == 32); > > +/* Action structure for NXAST_SET_TUNNEL_DST. > + * > + * Sets the encapsulating tunnel destination IP. */ > +struct nx_action_set_tunnel_dst { > + ovs_be16 type; /* OFPAT_VENDOR. */ > + ovs_be16 len; /* Length is 16. */ > + ovs_be32 vendor; /* NX_VENDOR_ID. */ > + ovs_be16 subtype; /* NXAST_SET_TUNNEL_DST. */ > + uint8_t pad[2]; > + ovs_be32 tun_dst; /* Destination IP. */ > +}; > +OFP_ASSERT(sizeof(struct nx_action_set_tunnel_dst) == 16); > + > #endif /* openflow/nicira-ext.h */ > diff --git a/lib/odp-util.c b/lib/odp-util.c > index de97fd2..8a2f76e 100644 > --- a/lib/odp-util.c > +++ b/lib/odp-util.c > @@ -2138,6 +2138,34 @@ commit_set_skb_mark_action(const struct flow > *flow, struct flow *base, > commit_set_action(odp_actions, OVS_KEY_ATTR_SKB_MARK, > &base->skb_mark, sizeof(base->skb_mark)); > } > + > +static void > +commit_set_ipv4_tunnel_action(const struct flow *flow, struct flow > *base, > + struct ofpbuf *odp_actions) > +{ > + struct ovs_key_ipv4_tunnel tmp; > + > + /* Don't use the full ipv4_tunnel action if just tun_id changed. > */ > + if (base->tunnel.ip_src == flow->tunnel.ip_src && > + base->tunnel.ip_dst == flow->tunnel.ip_dst) { > + return; > + } > + > + base->tunnel.tun_id = flow->tunnel.tun_id; > + base->tunnel.ip_dst = flow->tunnel.ip_dst; > + base->tunnel.ip_dst = flow->tunnel.ip_dst; > + > + tmp.tun_id = base->tunnel.tun_id; > + tmp.tun_flags = OVS_TNL_F_KEY | OVS_TNL_F_DONT_FRAGMENT; > + tmp.ipv4_src = base->tunnel.ip_src; > + tmp.ipv4_dst = base->tunnel.ip_dst; > + tmp.ipv4_tos = 0; > + tmp.ipv4_ttl = 64; > + > + commit_set_action(odp_actions, OVS_KEY_ATTR_IPV4_TUNNEL, > + &tmp, sizeof(tmp)); > +} > + > /* If any of the flow key data that ODP actions can modify are > different in > * 'base' and 'flow', appends ODP actions to 'odp_actions' that > change the flow > * key from 'base' into 'flow', and then changes 'base' the same > way. */ > @@ -2145,6 +2173,7 @@ void > commit_odp_actions(const struct flow *flow, struct flow *base, > struct ofpbuf *odp_actions) > { > + commit_set_ipv4_tunnel_action(flow, base, odp_actions); > commit_set_tun_id_action(flow, base, odp_actions); > commit_set_ether_addr_action(flow, base, odp_actions); > commit_vlan_action(flow, base, odp_actions); > diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c > index b758c7c..256a982 100644 > --- a/lib/ofp-actions.c > +++ b/lib/ofp-actions.c > @@ -294,6 +294,7 @@ ofpact_from_nxast(const union ofp_action *a, enum > ofputil_action_code code, > const struct nx_action_note *nan; > const struct nx_action_set_tunnel64 *nast64; > const struct nx_action_write_metadata *nawm; > + const struct nx_action_set_tunnel_dst *nastd; > struct ofpact_tunnel *tunnel; > enum ofperr error = 0; > > @@ -401,6 +402,11 @@ ofpact_from_nxast(const union ofp_action *a, > enum ofputil_action_code code, > case OFPUTIL_NXAST_CONTROLLER: > controller_from_openflow((const struct nx_action_controller > *) a, out); > break; > + > + case OFPUTIL_NXAST_SET_TUNNEL_DST: > + nastd = (const struct nx_action_set_tunnel_dst *) a; > + ofpact_put_SET_TUNNEL_DST(out)->tun_dst = nastd->tun_dst; > + break; > } > > return error; > @@ -1103,6 +1109,7 @@ ofpact_check__(const struct ofpact *a, const > struct flow *flow, int max_ports) > case OFPACT_POP_QUEUE: > case OFPACT_FIN_TIMEOUT: > case OFPACT_RESUBMIT: > + case OFPACT_SET_TUNNEL_DST: > return 0; > > case OFPACT_LEARN: > @@ -1297,6 +1304,13 @@ ofpact_fin_timeout_to_nxast(const struct > ofpact_fin_timeout *fin_timeout, > } > > static void > +ofpact_set_tunnel_dst_to_nxast(const struct ofpact_tunnel_dst > *tunnel_dst, > + struct ofpbuf *out) > +{ > + ofputil_put_NXAST_SET_TUNNEL_DST(out)->tun_dst = > tunnel_dst->tun_dst; > +} > + > +static void > ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) > { > switch (a->type) { > @@ -1369,6 +1383,10 @@ ofpact_to_nxast(const struct ofpact *a, struct > ofpbuf *out) > ofputil_put_NXAST_EXIT(out); > break; > > + case OFPACT_SET_TUNNEL_DST: > + ofpact_set_tunnel_dst_to_nxast(ofpact_get_SET_TUNNEL_DST(a), > out); > + break; > + > case OFPACT_OUTPUT: > case OFPACT_ENQUEUE: > case OFPACT_SET_VLAN_VID: > @@ -1496,6 +1514,7 @@ ofpact_to_openflow10(const struct ofpact *a, > struct ofpbuf *out) > case OFPACT_AUTOPATH: > case OFPACT_NOTE: > case OFPACT_EXIT: > + case OFPACT_SET_TUNNEL_DST: > ofpact_to_nxast(a, out); > break; > } > @@ -1638,6 +1657,7 @@ ofpact_to_openflow11(const struct ofpact *a, > struct ofpbuf *out) > case OFPACT_AUTOPATH: > case OFPACT_NOTE: > case OFPACT_EXIT: > + case OFPACT_SET_TUNNEL_DST: > ofpact_to_nxast(a, out); > break; > } > @@ -1763,6 +1783,7 @@ ofpact_outputs_to_port(const struct ofpact > *ofpact, uint16_t port) > case OFPACT_EXIT: > case OFPACT_CLEAR_ACTIONS: > case OFPACT_GOTO_TABLE: > + case OFPACT_SET_TUNNEL_DST: > default: > return false; > } > @@ -2059,6 +2080,10 @@ ofpact_format(const struct ofpact *a, struct > ds *s) > OVSINST_OFPIT11_GOTO_TABLE), > ofpact_get_GOTO_TABLE(a)->table_id); > break; > + > + case OFPACT_SET_TUNNEL_DST: > + ds_put_format(s, "set_tunnel_dst:"IP_FMT, > IP_ARGS(&ofpact_get_SET_TUNNEL_DST(a)->tun_dst)); > + break; > } > } > > diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h > index b6cf4ba..4ddced4 100644 > --- a/lib/ofp-actions.h > +++ b/lib/ofp-actions.h > @@ -74,6 +74,7 @@ > \ > /* Metadata. */ > \ > DEFINE_OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact) > \ > + DEFINE_OFPACT(SET_TUNNEL_DST, ofpact_tunnel_dst, ofpact) > \ > DEFINE_OFPACT(SET_QUEUE, ofpact_queue, ofpact) > \ > DEFINE_OFPACT(POP_QUEUE, ofpact_null, ofpact) > \ > DEFINE_OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact) > \ > @@ -318,6 +319,14 @@ struct ofpact_tunnel { > uint64_t tun_id; > }; > > +/* OFPACT_SET_TUNNEL_DST. > + * > + * Used for NXAST_SET_TUNNEL_DST. */ > +struct ofpact_tunnel_dst { > + struct ofpact ofpact; > + ovs_be32 tun_dst; > +}; > + > /* OFPACT_SET_QUEUE. > * > * Used for NXAST_SET_QUEUE. */ > diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c > index 65f023a..2338e6a 100644 > --- a/lib/ofp-parse.c > +++ b/lib/ofp-parse.c > @@ -562,6 +562,11 @@ parse_named_action(enum ofputil_action_code > code, const struct flow *flow, > case OFPUTIL_NXAST_CONTROLLER: > parse_controller(ofpacts, arg); > break; > + > + case OFPUTIL_NXAST_SET_TUNNEL_DST: > + str_to_ip(arg, &ip); > + ofpact_put_SET_TUNNEL_DST(ofpacts)->tun_dst = ip; > + break; > } > } > > diff --git a/lib/ofp-util.def b/lib/ofp-util.def > index 6d08d8a..d22672b 100644 > --- a/lib/ofp-util.def > +++ b/lib/ofp-util.def > @@ -62,6 +62,7 @@ NXAST_ACTION(NXAST_CONTROLLER, > nx_action_controller, 0, "controller") > NXAST_ACTION(NXAST_DEC_TTL_CNT_IDS, nx_action_cnt_ids, 1, NULL) > NXAST_ACTION(NXAST_WRITE_METADATA, nx_action_write_metadata, 0, > "write_metadata") > +NXAST_ACTION(NXAST_SET_TUNNEL_DST, nx_action_set_tunnel_dst, 0, > "set_tunnel_dst") > > #undef OFPAT10_ACTION > #undef OFPAT11_ACTION > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index ca0a065..968274b 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -6051,6 +6051,10 @@ do_xlate_actions(const struct ofpact *ofpacts, > size_t ofpacts_len, > xlate_table_action(ctx, ctx->flow.in_port, > ogt->table_id, true); > break; > } > + > + case OFPACT_SET_TUNNEL_DST: > + ctx->flow.tunnel.ip_dst = > ofpact_get_SET_TUNNEL_DST(a)->tun_dst; > + break; > } > } > > diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at > index 30fcf51..7146b70 100644 > --- a/tests/ofp-actions.at > +++ b/tests/ofp-actions.at > @@ -118,6 +118,9 @@ ffff 0010 00002320 0014 04d2 162e 02 00 > # actions=dec_ttl(32768,12345,90,765,1024) > ffff 0020 00002320 0015 000500000000 80003039005A02fd > 0400000000000000 > > +# actions=set_tunnel_dst:192.168.1.1 > +ffff 0010 00002320 0017 0000 C0A80101 > + > ]) > sed '/^[[#&]]/d' < test-data > input.txt > sed -n 's/^# //p; /^$/p' < test-data > expout > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > index 6a4dc23..f2a7728 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -231,6 +231,25 @@ AT_CHECK([tail -1 stdout], [0], > OVS_VSWITCHD_STOP > AT_CLEANUP > > +AT_SETUP([ofproto-dpif - set_tunnel_dst]) > +OVS_VSWITCHD_START > +ADD_OF_PORTS([br0], [1], [2], [3], [4], [5], [90]) > +AT_DATA([flows.txt], [dnl > +in_port=90 > actions=resubmit:1,resubmit:2,resubmit:3,resubmit:4,resubmit:5 > +in_port=1 actions=set_tunnel_dst:192.168.1.1,output:1 > +in_port=2 actions=set_tunnel_dst:192.168.1.1,output:2 > +in_port=3 > actions=set_tunnel_dst:192.168.1.2,set_tunnel_dst:192.168.1.3,output:3 > +in_port=4 > actions=set_tunnel_dst:192.168.1.4,set_tunnel_dst:192.168.1.3,output:4 > +in_port=5 actions=set_tunnel_dst:192.168.1.5 > +]) > +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) > +AT_CHECK([ovs-appctl ofproto/trace br0 > 'tun_id(0x1),in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], > [0], [stdout]) > +AT_CHECK([tail -1 stdout], [0], > + [Datapath actions: > set(ipv4_tunnel(tun_id=0x1,src=0.0.0.0,dst=192.168.1.1,tos=0x0,ttl=64,flags(df,key))),1,2,set(ipv4_tunnel(tun_id=0x1,src=0.0.0.0,dst=192.168.1.3,tos=0x0,ttl=64,flags(df,key))),3,4 > +]) > +OVS_VSWITCHD_STOP > +AT_CLEANUP > + > AT_SETUP([ofproto-dpif - controller]) > OVS_VSWITCHD_START([dnl > add-port br0 p1 -- set Interface p1 type=dummy > diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at > index 7b8f38f..bd1a143 100644 > --- a/tests/ovs-ofctl.at > +++ b/tests/ovs-ofctl.at > @@ -86,6 +86,7 @@ cookie=0x123456789abcdef hard_timeout=10 > priority=60000 actions=controller > actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note > tcp,tp_src=0x1230/0xfff0,tun_id=0x1234,cookie=0x5678,actions=flood > actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel:0x123456789 > +actions=set_tunnel_dst:192.168.1.1 > actions=multipath(eth_src, 50, hrw, 12, 0, > NXM_NX_REG0[0..3]),multipath(symmetric_l4, 1024, iter_hash, 5000, > 5050, NXM_NX_REG0[0..12]) > table=1,actions=drop > tun_id=0x1234000056780000/0xffff0000ffff0000,actions=drop > @@ -120,6 +121,7 @@ NXT_FLOW_MOD: ADD table:255 priority=60000 > cookie:0x123456789abcdef hard:10 acti > NXT_FLOW_MOD: ADD table:255 > > actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00 > NXT_FLOW_MOD: ADD table:255 tcp,tun_id=0x1234,tp_src=0x1230/0xfff0 > cookie:0x5678 actions=FLOOD > NXT_FLOW_MOD: ADD table:255 > actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel64:0x123456789 > +NXT_FLOW_MOD: ADD table:255 actions=set_tunnel_dst:192.168.1.1 > NXT_FLOW_MOD: ADD table:255 > > actions=multipath(eth_src,50,hrw,12,0,NXM_NX_REG0[0..3]),multipath(symmetric_l4,1024,iter_hash,5000,5050,NXM_NX_REG0[0..12]) > NXT_FLOW_MOD: ADD table:1 actions=drop > NXT_FLOW_MOD: ADD table:255 > tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop > -- > 1.7.9.5 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev