Fuel plugin to deploy OVS with NSH and DPDK
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

0002-ovs-nsh-support-push-and-pop-actions-for-vxlan-gpe-a.patch 94KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746
  1. From bd251cb247ac44e4362215da826e9bf1d6c61f27 Mon Sep 17 00:00:00 2001
  2. From: Yi Yang <yi.y.yang@intel.com>
  3. Date: Wed, 13 Apr 2016 11:15:42 +0800
  4. Subject: [PATCH 2/6] ovs-nsh: support push and pop actions for vxlan-gpe and
  5. Ethernet nsh
  6. Signed-off-by: Mengke Liu <mengke.liu@intel.com>
  7. Signed-off-by: Ricky Li <ricky.li@intel.com>
  8. Signed-off-by: Johnson Li <johnson.li@intel.com>
  9. Signed-off-by: Yi Yang <yi.y.yang@intel.com>
  10. ---
  11. datapath/actions.c | 73 ++++
  12. datapath/datapath.h | 2 +
  13. datapath/flow.c | 107 ++++++
  14. datapath/flow.h | 15 +
  15. datapath/flow_netlink.c | 81 ++++-
  16. datapath/linux/compat/include/linux/openvswitch.h | 174 +++++++++
  17. datapath/linux/compat/include/net/vxlan.h | 5 +-
  18. lib/dpif-netdev.c | 4 +
  19. lib/dpif.c | 4 +
  20. lib/flow.c | 19 +
  21. lib/flow.h | 21 +-
  22. lib/match.c | 190 ++++++++++
  23. lib/match.h | 24 ++
  24. lib/meta-flow.c | 256 ++++++++++++-
  25. lib/meta-flow.h | 174 +++++++++
  26. lib/netdev-vport.c | 10 +-
  27. lib/nx-match.c | 19 +
  28. lib/odp-execute.c | 10 +
  29. lib/odp-util.c | 417 +++++++++++++++++++++-
  30. lib/odp-util.h | 10 +-
  31. lib/ofp-actions.c | 154 +++++++-
  32. lib/ofp-actions.h | 6 +
  33. ofproto/ofproto-dpif-sflow.c | 2 +
  34. ofproto/ofproto-dpif-upcall.c | 19 +
  35. ofproto/ofproto-dpif-xlate.c | 22 ++
  36. tests/ofproto.at | 13 +-
  37. tests/tunnel.at | 157 ++++++++
  38. 27 files changed, 1976 insertions(+), 12 deletions(-)
  39. diff --git a/datapath/actions.c b/datapath/actions.c
  40. index dcf8591..16fc58f 100644
  41. --- a/datapath/actions.c
  42. +++ b/datapath/actions.c
  43. @@ -252,6 +252,63 @@ static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key,
  44. ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
  45. }
  46. +static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
  47. +{
  48. + if (!pskb_may_pull(skb, NSH_M_TYPE1_LEN))
  49. + return -ENOMEM;
  50. + else
  51. + __skb_pull(skb, NSH_M_TYPE1_LEN);
  52. +
  53. + return 0;
  54. +}
  55. +
  56. +static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key,
  57. + const struct ovs_action_push_nsh *nsh)
  58. +{
  59. +
  60. + if (nsh->nsh_mdtype == NSH_M_TYPE1) {
  61. + if (skb_cow_head(skb, NSH_M_TYPE1_LEN) < 0)
  62. + return -ENOMEM;
  63. +
  64. + skb_push(skb, NSH_M_TYPE1_LEN);
  65. + OVS_CB(skb)->nsh_header = skb->data;
  66. + memcpy(OVS_CB(skb)->nsh_header, nsh->header, NSH_M_TYPE1_LEN);
  67. + }
  68. + else
  69. + return -EINVAL;
  70. +
  71. + return 0;
  72. +}
  73. +
  74. +static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key)
  75. +{
  76. + if (!pskb_may_pull(skb, ENCAP_ETH_PUSH_HEADER_SIZE))
  77. + return -ENOMEM;
  78. + else
  79. + __skb_pull(skb, ENCAP_ETH_PUSH_HEADER_SIZE);
  80. +
  81. + return 0;
  82. +}
  83. +
  84. +static int push_eth(struct sk_buff *skb, struct sw_flow_key *key,
  85. + const struct ovs_action_push_eth *encap_eth)
  86. +{
  87. + if (encap_eth->encap_eth_type == htons(ETH_P_NSH)) {
  88. + if (skb_cow_head(skb, ENCAP_ETH_PUSH_HEADER_SIZE) < 0)
  89. + return -ENOMEM;
  90. +
  91. + skb_push(skb, ENCAP_ETH_PUSH_HEADER_SIZE);
  92. + OVS_CB(skb)->encap_eth_header = skb->data;
  93. + memcpy(OVS_CB(skb)->encap_eth_header, encap_eth->header, ENCAP_ETH_PUSH_HEADER_SIZE);
  94. + }
  95. + else {
  96. + return -EINVAL;
  97. + }
  98. +
  99. + return 0;
  100. +}
  101. +
  102. +
  103. /* 'src' is already properly masked. */
  104. static void ether_addr_copy_masked(u8 *dst_, const u8 *src_, const u8 *mask_)
  105. {
  106. @@ -1079,6 +1136,22 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
  107. err = pop_vlan(skb, key);
  108. break;
  109. + case OVS_ACTION_ATTR_PUSH_NSH:
  110. + err = push_nsh(skb, key, nla_data(a));
  111. + break;
  112. +
  113. + case OVS_ACTION_ATTR_POP_NSH:
  114. + err = pop_nsh(skb, key);
  115. + break;
  116. +
  117. + case OVS_ACTION_ATTR_PUSH_ETH:
  118. + err = push_eth(skb, key, nla_data(a));
  119. + break;
  120. +
  121. + case OVS_ACTION_ATTR_POP_ETH:
  122. + err = pop_eth(skb, key);
  123. + break;
  124. +
  125. case OVS_ACTION_ATTR_RECIRC:
  126. err = execute_recirc(dp, skb, key, a, rem);
  127. if (nla_is_last(a, rem)) {
  128. diff --git a/datapath/datapath.h b/datapath/datapath.h
  129. index ceb3372..b2d5fcd 100644
  130. --- a/datapath/datapath.h
  131. +++ b/datapath/datapath.h
  132. @@ -102,6 +102,8 @@ struct datapath {
  133. struct ovs_skb_cb {
  134. struct vport *input_vport;
  135. u16 mru;
  136. + struct nsh_hdr *nsh_header;
  137. + struct encap_eth_hdr *encap_eth_header;
  138. };
  139. #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
  140. diff --git a/datapath/flow.c b/datapath/flow.c
  141. index c97c9c9..67b2f1d 100644
  142. --- a/datapath/flow.c
  143. +++ b/datapath/flow.c
  144. @@ -44,6 +44,7 @@
  145. #include <net/ipv6.h>
  146. #include <net/mpls.h>
  147. #include <net/ndisc.h>
  148. +#include <net/vxlan.h>
  149. #include "datapath.h"
  150. #include "conntrack.h"
  151. @@ -318,6 +319,32 @@ static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
  152. return 0;
  153. }
  154. +static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key){
  155. + struct nsh_hdr *nsh_hdr = (struct nsh_hdr *)skb->data;
  156. + OVS_CB(skb)->nsh_header = nsh_hdr;
  157. + key->nsh.nsh_mdtype = nsh_hdr->base.mdtype;
  158. + if (key->nsh.nsh_mdtype != NSH_M_TYPE1)
  159. + return -EPERM;
  160. + key->nsh.nsh_np = nsh_hdr->base.proto;
  161. + key->nsh.nsi = nsh_hdr->base.svc_idx;
  162. + key->nsh.nsp = nsh_hdr->base.path_hdr << 8;
  163. + key->nsh.nshc1 = nsh_hdr->ctx.nshc1;
  164. + key->nsh.nshc2 = nsh_hdr->ctx.nshc2;
  165. + key->nsh.nshc3 = nsh_hdr->ctx.nshc3;
  166. + key->nsh.nshc4 = nsh_hdr->ctx.nshc4;
  167. + return 0;
  168. +}
  169. +
  170. +static void parse_encap_eth(struct sk_buff *skb, struct sw_flow_key *key){
  171. + struct encap_eth_hdr *encap_eth_header = (struct encap_eth_hdr *)skb->data;
  172. + OVS_CB(skb)->encap_eth_header = encap_eth_header;
  173. + key->encap_eth.encap_eth_type = encap_eth_header->encap_eth_type;
  174. + ether_addr_copy(key->encap_eth.encap_eth_src, encap_eth_header->encap_eth_src);
  175. + ether_addr_copy(key->encap_eth.encap_eth_dst, encap_eth_header->encap_eth_dst);
  176. +
  177. + return;
  178. +}
  179. +
  180. static __be16 parse_ethertype(struct sk_buff *skb)
  181. {
  182. struct llc_snap_hdr {
  183. @@ -457,6 +484,24 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
  184. int error;
  185. struct ethhdr *eth;
  186. + /* Extract ethernet+nsh if ethernet type is 0x894F */
  187. + eth = (struct ethhdr *)skb->data;
  188. + if (eth->h_proto == htons(ETH_P_NSH)) {
  189. + parse_encap_eth(skb, key);
  190. + __skb_pull(skb, ENCAP_ETH_LEN);
  191. +
  192. + if (unlikely(parse_nsh(skb, key)))
  193. + return -EINVAL;
  194. + if (key->nsh.nsh_mdtype == NSH_M_TYPE1 && key->nsh.nsh_np == NSH_P_ETHERNET) {
  195. + __skb_pull(skb, NSH_M_TYPE1_LEN);
  196. + } else {
  197. + return -EINVAL;
  198. + }
  199. + } else {
  200. + void *encap_eth_hdr = &(key->encap_eth);
  201. + memset(encap_eth_hdr, 0, ENCAP_ETH_LEN);
  202. + }
  203. +
  204. /* Flags are always used as part of stats */
  205. key->tp.flags = 0;
  206. @@ -676,11 +721,54 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
  207. }
  208. }
  209. }
  210. +
  211. + if (key->encap_eth.encap_eth_type == htons(ETH_P_NSH))
  212. + __skb_push(skb, ENCAP_ETH_LEN + NSH_M_TYPE1_LEN);
  213. +
  214. + return 0;
  215. +}
  216. +
  217. +static void ovs_key_nsh_init(struct sw_flow_key *key, __u16 len) {
  218. + void *nsh_hdr = &(key->nsh);
  219. + memset(nsh_hdr, 0, len);
  220. +}
  221. +
  222. +static int nsh_extract(struct sk_buff *skb, struct sw_flow_key *key) {
  223. + int ret;
  224. +
  225. + /* only support NSH MD tpye1 */
  226. + if (unlikely(parse_nsh(skb, key)))
  227. + return -EINVAL;
  228. + if (key->nsh.nsh_mdtype == NSH_M_TYPE1) {
  229. + __skb_pull(skb, NSH_M_TYPE1_LEN);
  230. + if(key->nsh.nsh_np == NSH_P_ETHERNET)
  231. + ret = key_extract(skb, key);
  232. + else
  233. + return -EINVAL;
  234. + __skb_push(skb, NSH_M_TYPE1_LEN);
  235. +
  236. + return ret;
  237. + } else {
  238. + ovs_key_nsh_init(key, NSH_M_TYPE1_LEN);
  239. + }
  240. +
  241. return 0;
  242. }
  243. +static bool is_nsh_header(const void *tun_opts, __be16 tun_flags) {
  244. + struct vxlan_metadata *md = NULL;
  245. + if (tun_opts && (tun_flags & TUNNEL_VXLAN_OPT))
  246. + md = (struct vxlan_metadata *)tun_opts;
  247. +
  248. + if (md && (md->gpe & VXLAN_GPE_NP_MASK) == VXLAN_GPE_NP_NSH)
  249. + return true;
  250. + else
  251. + return false;
  252. +}
  253. +
  254. int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
  255. {
  256. + ovs_key_nsh_init(key, NSH_M_TYPE1_LEN);
  257. return key_extract(skb, key);
  258. }
  259. @@ -715,6 +803,15 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
  260. key->ovs_flow_hash = 0;
  261. key->recirc_id = 0;
  262. + /* Extract NSH and inner Ethernet if NSH header exists */
  263. + if (tun_info && is_nsh_header(ip_tunnel_info_opts(tun_info), key->tun_key.tun_flags)) {
  264. + int ret ;
  265. + ret = nsh_extract(skb, key);
  266. + if (key->nsh.nsh_mdtype)
  267. + return ret;
  268. + } else {
  269. + ovs_key_nsh_init(key, NSH_M_TYPE1_LEN);
  270. + }
  271. return key_extract(skb, key);
  272. }
  273. @@ -729,5 +826,15 @@ int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
  274. if (err)
  275. return err;
  276. + /* Extract NSH and inner Ethernet if NSH header exists */
  277. + if (key && is_nsh_header(key->tun_opts, key->tun_key.tun_flags)) {
  278. + int ret ;
  279. + ret = nsh_extract(skb, key);
  280. + if (key->nsh.nsh_mdtype)
  281. + return ret;
  282. + } else {
  283. + ovs_key_nsh_init(key, NSH_M_TYPE1_LEN);
  284. + }
  285. +
  286. return key_extract(skb, key);
  287. }
  288. diff --git a/datapath/flow.h b/datapath/flow.h
  289. index c0b628a..c8ccd5f 100644
  290. --- a/datapath/flow.h
  291. +++ b/datapath/flow.h
  292. @@ -63,6 +63,21 @@ struct sw_flow_key {
  293. u32 skb_mark; /* SKB mark. */
  294. u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
  295. } __packed phy; /* Safe when right after 'tun_key'. */
  296. + struct {
  297. + u32 nshc1; /* NSH context C1-C4 */
  298. + u32 nshc2;
  299. + u32 nshc3;
  300. + u32 nshc4;
  301. + u32 nsp; /* NSH path id */
  302. + u8 nsi; /* NSH index */
  303. + u8 nsh_mdtype; /* NSH metadata type */
  304. + u8 nsh_np; /* NSH next protocol */
  305. + }__packed nsh; /* network service header */
  306. + struct {
  307. + u8 encap_eth_src[ETH_ALEN]; /* ENCAP ethernet source address. */
  308. + u8 encap_eth_dst[ETH_ALEN]; /* ENCAP ethernet destination address. */
  309. + u16 encap_eth_type; /* ENCAP ethernet type. */
  310. + } encap_eth;
  311. u32 ovs_flow_hash; /* Datapath computed hash value. */
  312. u32 recirc_id; /* Recirculation ID. */
  313. struct {
  314. diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
  315. index 351a504..ebfae37 100644
  316. --- a/datapath/flow_netlink.c
  317. +++ b/datapath/flow_netlink.c
  318. @@ -284,7 +284,7 @@ size_t ovs_key_attr_size(void)
  319. /* Whenever adding new OVS_KEY_ FIELDS, we should consider
  320. * updating this function.
  321. */
  322. - BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 26);
  323. + BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 28);
  324. return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
  325. + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
  326. @@ -297,6 +297,8 @@ size_t ovs_key_attr_size(void)
  327. + nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */
  328. + nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
  329. + nla_total_size(16) /* OVS_KEY_ATTR_CT_LABELS */
  330. + + nla_total_size(24) /* OVS_KEY_ATTR_NSH */
  331. + + nla_total_size(14) /* OVS_KEY_ATTR_ENCAP_ETH */
  332. + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
  333. + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
  334. + nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
  335. @@ -334,6 +336,8 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
  336. [OVS_KEY_ATTR_PRIORITY] = { .len = sizeof(u32) },
  337. [OVS_KEY_ATTR_IN_PORT] = { .len = sizeof(u32) },
  338. [OVS_KEY_ATTR_SKB_MARK] = { .len = sizeof(u32) },
  339. + [OVS_KEY_ATTR_NSH] = { .len = sizeof(struct ovs_key_nsh) },
  340. + [OVS_KEY_ATTR_ENCAP_ETH] = { .len = sizeof(struct ovs_key_encap_eth) },
  341. [OVS_KEY_ATTR_ETHERNET] = { .len = sizeof(struct ovs_key_ethernet) },
  342. [OVS_KEY_ATTR_VLAN] = { .len = sizeof(__be16) },
  343. [OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },
  344. @@ -869,6 +873,42 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
  345. if (err)
  346. return err;
  347. + if (attrs & (1ULL << OVS_KEY_ATTR_NSH)) {
  348. + const struct ovs_key_nsh *nsh_key;
  349. +
  350. + nsh_key = nla_data(a[OVS_KEY_ATTR_NSH]);
  351. + SW_FLOW_KEY_PUT(match, nsh.nshc1,
  352. + nsh_key->nshc1, is_mask);
  353. + SW_FLOW_KEY_PUT(match, nsh.nshc2,
  354. + nsh_key->nshc2, is_mask);
  355. + SW_FLOW_KEY_PUT(match, nsh.nshc3,
  356. + nsh_key->nshc3, is_mask);
  357. + SW_FLOW_KEY_PUT(match, nsh.nshc4,
  358. + nsh_key->nshc4, is_mask);
  359. + SW_FLOW_KEY_PUT(match, nsh.nsh_mdtype,
  360. + nsh_key->nsh_mdtype, is_mask);
  361. + SW_FLOW_KEY_PUT(match, nsh.nsh_np,
  362. + nsh_key->nsh_np, is_mask);
  363. + SW_FLOW_KEY_PUT(match, nsh.nsp,
  364. + nsh_key->nsp, is_mask);
  365. + SW_FLOW_KEY_PUT(match, nsh.nsi,
  366. + nsh_key->nsi, is_mask);
  367. + attrs &= ~(1ULL << OVS_KEY_ATTR_NSH);
  368. + }
  369. +
  370. + if (attrs & (1ULL << OVS_KEY_ATTR_ENCAP_ETH)) {
  371. + const struct ovs_key_encap_eth *encap_eth_key;
  372. +
  373. + encap_eth_key = nla_data(a[OVS_KEY_ATTR_ENCAP_ETH]);
  374. + SW_FLOW_KEY_MEMCPY(match, encap_eth.encap_eth_src,
  375. + encap_eth_key->encap_eth_src, ETH_ALEN, is_mask);
  376. + SW_FLOW_KEY_MEMCPY(match, encap_eth.encap_eth_dst,
  377. + encap_eth_key->encap_eth_dst, ETH_ALEN, is_mask);
  378. + SW_FLOW_KEY_PUT(match, encap_eth.encap_eth_type,
  379. + encap_eth_key->encap_eth_type, is_mask);
  380. + attrs &= ~(1ULL << OVS_KEY_ATTR_ENCAP_ETH);
  381. + }
  382. +
  383. if (attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) {
  384. const struct ovs_key_ethernet *eth_key;
  385. @@ -1386,6 +1426,35 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
  386. if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
  387. goto nla_put_failure;
  388. + if ((swkey->nsh.nsh_mdtype || is_mask)) {
  389. + struct ovs_key_nsh *nsh_key;
  390. +
  391. + nla = nla_reserve(skb, OVS_KEY_ATTR_NSH, sizeof(*nsh_key));
  392. + if (!nla)
  393. + goto nla_put_failure;
  394. + nsh_key = nla_data(nla);
  395. + nsh_key->nsi = output->nsh.nsi;
  396. + nsh_key->nsp = output->nsh.nsp;
  397. + nsh_key->nsh_mdtype= output->nsh.nsh_mdtype;
  398. + nsh_key->nsh_np= output->nsh.nsh_np;
  399. + nsh_key->nshc1= output->nsh.nshc1;
  400. + nsh_key->nshc2 = output->nsh.nshc2;
  401. + nsh_key->nshc3 = output->nsh.nshc3;
  402. + nsh_key->nshc4 = output->nsh.nshc4;
  403. + }
  404. +
  405. + if ((swkey->encap_eth.encap_eth_type || is_mask)) {
  406. + struct ovs_key_encap_eth *encap_eth_key;
  407. +
  408. + nla = nla_reserve(skb, OVS_KEY_ATTR_ENCAP_ETH, sizeof(*encap_eth_key));
  409. + if (!nla)
  410. + goto nla_put_failure;
  411. + encap_eth_key = nla_data(nla);
  412. + memcpy(encap_eth_key->encap_eth_src, output->encap_eth.encap_eth_src, ETH_ALEN);
  413. + memcpy(encap_eth_key->encap_eth_dst, output->encap_eth.encap_eth_dst, ETH_ALEN);
  414. + encap_eth_key->encap_eth_type= output->encap_eth.encap_eth_type;
  415. + }
  416. +
  417. if ((swkey->tun_key.u.ipv4.dst || is_mask)) {
  418. const void *opts = NULL;
  419. @@ -2182,6 +2251,10 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
  420. [OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
  421. [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
  422. [OVS_ACTION_ATTR_POP_VLAN] = 0,
  423. + [OVS_ACTION_ATTR_PUSH_NSH] = sizeof(struct ovs_action_push_nsh),
  424. + [OVS_ACTION_ATTR_POP_NSH] = 0,
  425. + [OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
  426. + [OVS_ACTION_ATTR_POP_ETH] = 0,
  427. [OVS_ACTION_ATTR_SET] = (u32)-1,
  428. [OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
  429. [OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
  430. @@ -2226,6 +2299,12 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
  431. break;
  432. }
  433. + case OVS_ACTION_ATTR_PUSH_NSH:
  434. + case OVS_ACTION_ATTR_POP_NSH:
  435. + case OVS_ACTION_ATTR_PUSH_ETH:
  436. + case OVS_ACTION_ATTR_POP_ETH:
  437. + break;
  438. +
  439. case OVS_ACTION_ATTR_POP_VLAN:
  440. vlan_tci = htons(0);
  441. break;
  442. diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
  443. index 44adb81..187bb9b 100644
  444. --- a/datapath/linux/compat/include/linux/openvswitch.h
  445. +++ b/datapath/linux/compat/include/linux/openvswitch.h
  446. @@ -42,6 +42,7 @@
  447. #include <linux/types.h>
  448. #include <linux/if_ether.h>
  449. +#include <asm/byteorder.h>
  450. /**
  451. * struct ovs_header - header for OVS Generic Netlink messages.
  452. @@ -328,6 +329,9 @@ enum ovs_key_attr {
  453. OVS_KEY_ATTR_ENCAP, /* Nested set of encapsulated attributes. */
  454. OVS_KEY_ATTR_PRIORITY, /* u32 skb->priority */
  455. OVS_KEY_ATTR_IN_PORT, /* u32 OVS dp port number */
  456. + OVS_KEY_ATTR_NSH, /* struct ovs_key_nsh. Only support NSH MD
  457. + type 1 now */
  458. + OVS_KEY_ATTR_ENCAP_ETH, /* struct ovs_key_encap_eth */
  459. OVS_KEY_ATTR_ETHERNET, /* struct ovs_key_ethernet */
  460. OVS_KEY_ATTR_VLAN, /* be16 VLAN TCI */
  461. OVS_KEY_ATTR_ETHERTYPE, /* be16 Ethernet type */
  462. @@ -401,6 +405,24 @@ enum ovs_frag_type {
  463. #define OVS_FRAG_TYPE_MAX (__OVS_FRAG_TYPE_MAX - 1)
  464. +struct ovs_key_nsh {
  465. + __u32 nshc1;
  466. + __u32 nshc2;
  467. + __u32 nshc3;
  468. + __u32 nshc4;
  469. + __u32 nsp;
  470. + __u8 nsi;
  471. + __u8 nsh_mdtype;
  472. + __u8 nsh_np;
  473. + __u8 reserved;
  474. +};
  475. +
  476. +struct ovs_key_encap_eth {
  477. + __u8 encap_eth_src[ETH_ALEN];
  478. + __u8 encap_eth_dst[ETH_ALEN];
  479. + __u16 encap_eth_type;
  480. +};
  481. +
  482. struct ovs_key_ethernet {
  483. __u8 eth_src[ETH_ALEN];
  484. __u8 eth_dst[ETH_ALEN];
  485. @@ -630,6 +652,154 @@ struct ovs_action_push_vlan {
  486. __be16 vlan_tci; /* 802.1Q TCI (VLAN ID and priority). */
  487. };
  488. +/*
  489. + * Network Service Header:
  490. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  491. + * |Ver|O|C|R|R|R|R|R|R| Length | MD Type | Next Proto |
  492. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  493. + * | Service Path ID | Service Index |
  494. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  495. + * Ver = The version field is used to ensure backward compatibility
  496. + * going forward with future NSH updates. It MUST be set to 0x0
  497. + * by the sender, in this first revision of NSH.
  498. + *
  499. + * O = OAM. when set to 0x1 indicates that this packet is an operations
  500. + * and management (OAM) packet. The receiving SFF and SFs nodes
  501. + * MUST examine the payload and take appropriate action.
  502. + *
  503. + * C = context. Indicates that a critical metadata TLV is present.
  504. + *
  505. + * Length : total length, in 4-byte words, of NSH including the Base
  506. + * Header, the Service Path Header and the optional variable
  507. + * TLVs.
  508. + * MD Type: indicates the format of NSH beyond the mandatory Base Header
  509. + * and the Service Path Header.
  510. + *
  511. + * Next Protocol: indicates the protocol type of the original packet. A
  512. + * new IANA registry will be created for protocol type.
  513. + *
  514. + * Service Path Identifier (SPI): identifies a service path.
  515. + * Participating nodes MUST use this identifier for Service
  516. + * Function Path selection.
  517. + *
  518. + * Service Index (SI): provides location within the SFP.
  519. + *
  520. + * [0] https://tools.ietf.org/html/draft-ietf-sfc-nsh-01
  521. + */
  522. +
  523. +struct nsh_base {
  524. +#if defined(__LITTLE_ENDIAN_BITFIELD)
  525. +
  526. + __u8 reserved_flags1:4;
  527. + __u8 context_flag:1;
  528. + __u8 oam_flag:1;
  529. + __u8 version:2;
  530. +
  531. + __u8 length:6;
  532. + __u8 reserved_flags2:2;
  533. +#elif defined(__BIG_ENDIAN_BITFIELD)
  534. +
  535. + __u8 version:2;
  536. + __u8 oam_flag:1;
  537. + __u8 context_flag:1;
  538. + __u8 reserved_flags1:4;
  539. +
  540. + __u8 reserved_flags2:2;
  541. + __u8 length:6;
  542. +#else
  543. +#error "Bitfield Endianess not defined."
  544. +#endif
  545. + __u8 mdtype;
  546. + __u8 proto;
  547. + union {
  548. + struct {
  549. + __u8 svc_path[3];
  550. + __u8 svc_idx;
  551. + };
  552. + __be32 path_hdr;
  553. + };
  554. +};
  555. +
  556. +
  557. +/**
  558. + * struct nsh_ctx - Keeps track of NSH context data
  559. + * @c<1-4>: NSH Contexts.
  560. + */
  561. +struct nsh_ctx {
  562. + __be32 nshc1;
  563. + __be32 nshc2;
  564. + __be32 nshc3;
  565. + __be32 nshc4;
  566. +};
  567. +
  568. +/**
  569. + * struct nshdr - Network Service header
  570. + * @nsh_base: Network Service Base Header.
  571. + * @nsh_ctx: Network Service Context Header.
  572. + */
  573. +struct nsh_hdr {
  574. + struct nsh_base base;
  575. + struct nsh_ctx ctx;
  576. +};
  577. +
  578. +
  579. +#define ETH_P_NSH 0x894F /* Ethertype for NSH */
  580. +
  581. +/* NSH Base Header Next Protocol */
  582. +#define NSH_P_IPV4 0x01
  583. +#define NSH_P_IPV6 0x02
  584. +#define NSH_P_ETHERNET 0x03
  585. +
  586. +/* MD Type Registry */
  587. +#define NSH_M_TYPE1 0x01
  588. +#define NSH_M_EXP1 0xFE
  589. +#define NSH_M_EXP2 0xFF
  590. +
  591. +#define NSH_DST_PORT 4790 /* UDP Port for NSH on VXLAN */
  592. +
  593. +#define NSH_M_TYPE1_LEN 24
  594. +
  595. +/* Used for masking nsp and nsi values in field nsp below */
  596. +#define NSH_M_NSP 0x00FFFFFF
  597. +#define NSH_M_NSI 0xFF000000
  598. +
  599. +/* NSH header for MD type 1. Unit is bytes */
  600. +#define NSH_PUSH_TYPE1_HEADER_SIZE 24
  601. +#define NSH_PUSH_HEADER_SIZE 256
  602. +
  603. +#define ENCAP_ETH_LEN 14
  604. +
  605. +/**
  606. + * struct encap_eth - encap ethernet header for ethernet NSH
  607. + * @encap_eth_src: encap ethernet source address.
  608. + * @encap_eth_src: encap ethernet destination address.
  609. + * @encap_eth_type: encap ethernet type.
  610. + */
  611. +struct encap_eth_hdr {
  612. + __u8 encap_eth_dst[ETH_ALEN];
  613. + __u8 encap_eth_src[ETH_ALEN];
  614. + __u16 encap_eth_type;
  615. +};
  616. +
  617. +#define ENCAP_ETH_PUSH_HEADER_SIZE 14
  618. +/**
  619. + * struct ovs_action_push_nsh - %OVS_ACTION_ATTR_PUSH_NSH action argument.
  620. + * @header
  621. + */
  622. +struct ovs_action_push_nsh {
  623. + uint8_t nsh_mdtype;
  624. + uint8_t header[NSH_PUSH_HEADER_SIZE];
  625. +};
  626. +
  627. +/**
  628. + * struct ovs_action_push_nsh - %OVS_ACTION_ATTR_PUSH_NSH action argument.
  629. + * @header
  630. + */
  631. +struct ovs_action_push_eth {
  632. + uint16_t encap_eth_type;
  633. + uint8_t header[ENCAP_ETH_PUSH_HEADER_SIZE];
  634. +};
  635. +
  636. /* Data path hash algorithm for computing Datapath hash.
  637. *
  638. * The algorithm type only specifies the fields in a flow
  639. @@ -793,6 +963,10 @@ enum ovs_action_attr {
  640. OVS_ACTION_ATTR_SET, /* One nested OVS_KEY_ATTR_*. */
  641. OVS_ACTION_ATTR_PUSH_VLAN, /* struct ovs_action_push_vlan. */
  642. OVS_ACTION_ATTR_POP_VLAN, /* No argument. */
  643. + OVS_ACTION_ATTR_PUSH_NSH, /* struct ovs_action_push_nsh. */
  644. + OVS_ACTION_ATTR_POP_NSH, /* No argument. */
  645. + OVS_ACTION_ATTR_PUSH_ETH, /* struct ovs_action_push_eth. */
  646. + OVS_ACTION_ATTR_POP_ETH, /* No argument. */
  647. OVS_ACTION_ATTR_SAMPLE, /* Nested OVS_SAMPLE_ATTR_*. */
  648. OVS_ACTION_ATTR_RECIRC, /* u32 recirc_id. */
  649. OVS_ACTION_ATTR_HASH, /* struct ovs_action_hash. */
  650. diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
  651. index 2bfc3f8..3aeac88 100644
  652. --- a/datapath/linux/compat/include/net/vxlan.h
  653. +++ b/datapath/linux/compat/include/net/vxlan.h
  654. @@ -85,7 +85,7 @@ struct vxlanhdr_gbp {
  655. #define VXLAN_GBP_ID_MASK (0xFFFF)
  656. /*
  657. - * VXLAN Generic Protocol Extension Extension:
  658. + * VXLAN Generic Protocol Extension:
  659. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  660. * |R|R|Ver|I|P|R|O|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R| Next Proto |
  661. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  662. @@ -103,6 +103,9 @@ struct vxlanhdr_gbp {
  663. * O = OAM Flag Bit. The O bit is set to indicate that the packet
  664. * is an OAM packet.
  665. *
  666. + * Next Protocol = This 8 bit field indicates the protocol header
  667. + * immediately following the VXLAN GPE header.
  668. + *
  669. * [1] https://www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-01.txt
  670. */
  671. diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
  672. index 119dc2d..8e67bfd 100644
  673. --- a/lib/dpif-netdev.c
  674. +++ b/lib/dpif-netdev.c
  675. @@ -3874,6 +3874,10 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
  676. VLOG_WARN("Cannot execute conntrack action in userspace.");
  677. break;
  678. + case OVS_ACTION_ATTR_PUSH_NSH:
  679. + case OVS_ACTION_ATTR_POP_NSH:
  680. + case OVS_ACTION_ATTR_PUSH_ETH:
  681. + case OVS_ACTION_ATTR_POP_ETH:
  682. case OVS_ACTION_ATTR_PUSH_VLAN:
  683. case OVS_ACTION_ATTR_POP_VLAN:
  684. case OVS_ACTION_ATTR_PUSH_MPLS:
  685. diff --git a/lib/dpif.c b/lib/dpif.c
  686. index a784de7..b5265c4 100644
  687. --- a/lib/dpif.c
  688. +++ b/lib/dpif.c
  689. @@ -1139,6 +1139,10 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet **packets, int cnt,
  690. }
  691. case OVS_ACTION_ATTR_HASH:
  692. + case OVS_ACTION_ATTR_PUSH_NSH:
  693. + case OVS_ACTION_ATTR_POP_NSH:
  694. + case OVS_ACTION_ATTR_PUSH_ETH:
  695. + case OVS_ACTION_ATTR_POP_ETH:
  696. case OVS_ACTION_ATTR_PUSH_VLAN:
  697. case OVS_ACTION_ATTR_POP_VLAN:
  698. case OVS_ACTION_ATTR_PUSH_MPLS:
  699. diff --git a/lib/flow.c b/lib/flow.c
  700. index d24bdc9..fc8b98c 100644
  701. --- a/lib/flow.c
  702. +++ b/lib/flow.c
  703. @@ -1289,6 +1289,25 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc,
  704. WC_MASK_FIELD(wc, tunnel.tun_id);
  705. }
  706. + /* NSH fields wildcarded */
  707. + if (flow->nsh_mdtype) {
  708. + WC_MASK_FIELD(wc, nshc1);
  709. + WC_MASK_FIELD(wc, nshc2);
  710. + WC_MASK_FIELD(wc, nshc3);
  711. + WC_MASK_FIELD(wc, nshc4);
  712. + WC_MASK_FIELD(wc, nsh_mdtype);
  713. + WC_MASK_FIELD(wc, nsh_np);
  714. + WC_MASK_FIELD(wc, nsp);
  715. + WC_MASK_FIELD(wc, nsi);
  716. + }
  717. +
  718. + /* ENCAP Eth wildcarded */
  719. + if (flow->encap_eth_type) {
  720. + WC_MASK_FIELD(wc, encap_eth_src);
  721. + WC_MASK_FIELD(wc, encap_eth_dst);
  722. + WC_MASK_FIELD(wc, encap_eth_type);
  723. + }
  724. +
  725. /* metadata, regs, and conj_id wildcarded. */
  726. WC_MASK_FIELD(wc, skb_priority);
  727. diff --git a/lib/flow.h b/lib/flow.h
  728. index dc7130d..a8677b1 100644
  729. --- a/lib/flow.h
  730. +++ b/lib/flow.h
  731. @@ -111,6 +111,23 @@ struct flow {
  732. ofp_port_t actset_output; /* Output port in action set. */
  733. uint8_t pad2[2]; /* Pad to 64 bits. */
  734. + /* NSH (64-bit aligned) */
  735. + ovs_be32 nshc1;
  736. + ovs_be32 nshc2;
  737. + ovs_be32 nshc3;
  738. + ovs_be32 nshc4;
  739. + ovs_be32 nsp;
  740. + uint8_t nsi;
  741. + uint8_t nsh_mdtype;
  742. + uint8_t nsh_np;
  743. + uint8_t pad3;
  744. +
  745. + /* ENCAP_ETH (64-bit aligned) */
  746. + struct eth_addr encap_eth_src; /* Encap ethernet source address. */
  747. + struct eth_addr encap_eth_dst; /* Encap ethernet destination address. */
  748. + ovs_be16 encap_eth_type; /* Encap ethernet frame type. */
  749. + uint8_t pad4[2];
  750. +
  751. /* L2, Order the same as in the Ethernet header! (64-bit aligned) */
  752. struct eth_addr dl_dst; /* Ethernet destination address. */
  753. struct eth_addr dl_src; /* Ethernet source address. */
  754. @@ -132,7 +149,7 @@ struct flow {
  755. struct eth_addr arp_sha; /* ARP/ND source hardware address. */
  756. struct eth_addr arp_tha; /* ARP/ND target hardware address. */
  757. ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */
  758. - ovs_be16 pad3; /* Pad to 64 bits. */
  759. + ovs_be16 pad5; /* Pad to 64 bits. */
  760. /* L4 (64-bit aligned) */
  761. ovs_be16 tp_src; /* TCP/UDP/SCTP source port/ICMP type. */
  762. @@ -158,7 +175,7 @@ BUILD_ASSERT_DECL(sizeof(struct flow_tnl) % sizeof(uint64_t) == 0);
  763. /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
  764. BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t)
  765. - == sizeof(struct flow_tnl) + 216
  766. + == sizeof(struct flow_tnl) + 256
  767. && FLOW_WC_SEQ == 35);
  768. /* Incremental points at which flow classification may be performed in
  769. diff --git a/lib/match.c b/lib/match.c
  770. index 52437c9..3db2a2b 100644
  771. --- a/lib/match.c
  772. +++ b/lib/match.c
  773. @@ -862,6 +862,152 @@ match_set_nd_target_masked(struct match *match,
  774. match->wc.masks.nd_target = *mask;
  775. }
  776. +void
  777. +match_set_nsp_masked(struct match *match, ovs_be32 nsp, ovs_be32 mask)
  778. +{
  779. + match->wc.masks.nsp = mask;
  780. + match->flow.nsp = nsp & mask;
  781. +}
  782. +
  783. +void
  784. +match_set_nsi_masked(struct match *match, uint8_t nsi, uint8_t mask)
  785. +{
  786. + match->wc.masks.nsi = mask;
  787. + match->flow.nsi = nsi & mask;
  788. +}
  789. +
  790. +void
  791. +match_set_nsh_mdtype_masked(struct match *match, uint8_t nsh_mdtype, uint8_t mask)
  792. +{
  793. + match->wc.masks.nsh_mdtype = mask;
  794. + match->flow.nsh_mdtype = nsh_mdtype & mask;
  795. +}
  796. +
  797. +void
  798. +match_set_nsh_np_masked(struct match *match, uint8_t nsh_np, uint8_t mask)
  799. +{
  800. + match->wc.masks.nsh_np = mask;
  801. + match->flow.nsh_np = nsh_np & mask;
  802. +}
  803. +
  804. +void
  805. +match_set_encap_eth_src_masked(struct match *match,
  806. + const struct eth_addr encap_eth_src,
  807. + const struct eth_addr mask)
  808. +{
  809. + set_eth_masked(encap_eth_src, mask, &match->flow.encap_eth_src, &match->wc.masks.encap_eth_src);
  810. +}
  811. +
  812. +void
  813. +match_set_encap_eth_dst_masked(struct match *match,
  814. + const struct eth_addr encap_eth_dst,
  815. + const struct eth_addr mask)
  816. +{
  817. + set_eth_masked(encap_eth_dst, mask, &match->flow.encap_eth_dst, &match->wc.masks.encap_eth_dst);
  818. +}
  819. +
  820. +void
  821. +match_set_encap_eth_type_masked(struct match *match, ovs_be16 encap_eth_type, ovs_be16 mask)
  822. +{
  823. + match->wc.masks.encap_eth_type = mask;
  824. + match->flow.encap_eth_type = encap_eth_type & mask;
  825. +}
  826. +
  827. +void
  828. +match_set_nshc1_masked(struct match *match, ovs_be32 nshc1, ovs_be32 mask)
  829. +{
  830. + match->wc.masks.nshc1 = mask;
  831. + match->flow.nshc1 = nshc1 & mask;
  832. +}
  833. +
  834. +void
  835. +match_set_nshc2_masked(struct match *match, ovs_be32 nshc2, ovs_be32 mask)
  836. +{
  837. + match->wc.masks.nshc2 = mask;
  838. + match->flow.nshc2 = nshc2 & mask;
  839. +}
  840. +
  841. +void
  842. +match_set_nshc3_masked(struct match *match, ovs_be32 nshc3, ovs_be32 mask)
  843. +{
  844. + match->wc.masks.nshc3 = mask;
  845. + match->flow.nshc3 = nshc3 & mask;
  846. +}
  847. +
  848. +void
  849. +match_set_nshc4_masked(struct match *match, ovs_be32 nshc4, ovs_be32 mask)
  850. +{
  851. + match->wc.masks.nshc4 = mask;
  852. + match->flow.nshc4 = nshc4 & mask;
  853. +}
  854. +
  855. +void
  856. +match_set_nsp(struct match *match, ovs_be32 nsp)
  857. +{
  858. + match_set_nsp_masked(match, nsp, OVS_BE32_MAX);
  859. +}
  860. +
  861. +void
  862. +match_set_nsi(struct match *match, uint8_t nsi)
  863. +{
  864. + match_set_nsi_masked(match, nsi, UINT8_MAX);
  865. +}
  866. +
  867. +void
  868. +match_set_nsh_mdtype(struct match *match, uint8_t nsh_mdtype)
  869. +{
  870. + match_set_nsh_mdtype_masked(match, nsh_mdtype, UINT8_MAX);
  871. +}
  872. +
  873. +void
  874. +match_set_nsh_np(struct match *match, uint8_t nsh_np)
  875. +{
  876. + match_set_nsh_np_masked(match, nsh_np, UINT8_MAX);
  877. +}
  878. +
  879. +void
  880. +match_set_nshc1(struct match *match, ovs_be32 nshc1)
  881. +{
  882. + match_set_nshc1_masked(match, nshc1, OVS_BE32_MAX);
  883. +}
  884. +
  885. +void
  886. +match_set_nshc2(struct match *match, ovs_be32 nshc2)
  887. +{
  888. + match_set_nshc2_masked(match, nshc2, OVS_BE32_MAX);
  889. +}
  890. +
  891. +void
  892. +match_set_nshc3(struct match *match, ovs_be32 nshc3)
  893. +{
  894. + match_set_nshc3_masked(match, nshc3, OVS_BE32_MAX);
  895. +}
  896. +
  897. +void
  898. +match_set_nshc4(struct match *match, ovs_be32 nshc4)
  899. +{
  900. + match_set_nshc4_masked(match, nshc4, OVS_BE32_MAX);
  901. +}
  902. +
  903. +void
  904. +match_set_encap_eth_src(struct match *match, const struct eth_addr encap_eth_src)
  905. +{
  906. + set_eth(encap_eth_src, &match->flow.encap_eth_src, &match->wc.masks.encap_eth_src);
  907. +}
  908. +
  909. +void
  910. +match_set_encap_eth_dst(struct match *match, const struct eth_addr encap_eth_dst)
  911. +{
  912. + set_eth(encap_eth_dst, &match->flow.encap_eth_dst, &match->wc.masks.encap_eth_dst);
  913. +}
  914. +
  915. +void
  916. +match_set_encap_eth_type(struct match *match, uint16_t encap_eth_type)
  917. +{
  918. + match_set_encap_eth_type_masked(match, encap_eth_type, UINT16_MAX);
  919. +}
  920. +
  921. +
  922. /* Returns true if 'a' and 'b' wildcard the same fields and have the same
  923. * values for fixed fields, otherwise false. */
  924. bool
  925. @@ -1155,6 +1301,50 @@ match_format(const struct match *match, struct ds *s, int priority)
  926. format_ct_label_masked(s, &f->ct_label, &wc->masks.ct_label);
  927. }
  928. + if (wc->masks.nsi) {
  929. + ds_put_format(s, "nsi=%"PRIu8",", f->nsi);
  930. + }
  931. +
  932. + if (wc->masks.nsh_mdtype) {
  933. + ds_put_format(s, "nsh_mdtype=%"PRIu8",", f->nsh_mdtype);
  934. + }
  935. +
  936. + if (wc->masks.nsh_np) {
  937. + ds_put_format(s, "nsh_np=%"PRIu8",", f->nsh_np);
  938. + }
  939. +
  940. + if (wc->masks.nsp) {
  941. + format_be32_masked(s, "nsp", f->nsp,
  942. + wc->masks.nsp);
  943. + }
  944. +
  945. + if (wc->masks.nshc1) {
  946. + format_be32_masked(s, "nshc1", f->nshc1,
  947. + wc->masks.nshc1);
  948. + }
  949. +
  950. + if (wc->masks.nshc2) {
  951. + format_be32_masked(s, "nshc2", f->nshc2,
  952. + wc->masks.nshc2);
  953. + }
  954. +
  955. + if (wc->masks.nshc3) {
  956. + format_be32_masked(s, "nshc3", f->nshc3,
  957. + wc->masks.nshc3);
  958. + }
  959. +
  960. + if (wc->masks.nshc4) {
  961. + format_be32_masked(s, "nshc4", f->nshc4,
  962. + wc->masks.nshc4);
  963. + }
  964. +
  965. + if (wc->masks.encap_eth_type) {
  966. + ds_put_format(s, "encap_eth_type=%"PRIu16",", f->encap_eth_type);
  967. + }
  968. +
  969. + format_eth_masked(s, "encap_eth_src", f->encap_eth_src, wc->masks.encap_eth_src);
  970. + format_eth_masked(s, "encap_eth_dst", f->encap_eth_dst, wc->masks.encap_eth_dst);
  971. +
  972. if (wc->masks.dl_type) {
  973. skip_type = true;
  974. if (f->dl_type == htons(ETH_TYPE_IP)) {
  975. diff --git a/lib/match.h b/lib/match.h
  976. index 48aa0b1..529350e 100644
  977. --- a/lib/match.h
  978. +++ b/lib/match.h
  979. @@ -165,6 +165,30 @@ void match_set_nd_target(struct match *, const struct in6_addr *);
  980. void match_set_nd_target_masked(struct match *, const struct in6_addr *,
  981. const struct in6_addr *);
  982. +void match_set_nsp_masked(struct match *, ovs_be32 nsp, ovs_be32 mask);
  983. +void match_set_nsi_masked(struct match *match, uint8_t nsi, uint8_t mask);
  984. +void match_set_nsh_mdtype_masked(struct match *match, uint8_t nsh_mdtype, uint8_t mask);
  985. +void match_set_nsh_np_masked(struct match *match, uint8_t nsh_np, uint8_t mask);
  986. +void match_set_nshc1_masked(struct match *, ovs_be32 nshc1, ovs_be32 mask);
  987. +void match_set_nshc2_masked(struct match *, ovs_be32 nshc2, ovs_be32 mask);
  988. +void match_set_nshc3_masked(struct match *, ovs_be32 nshc3, ovs_be32 mask);
  989. +void match_set_nshc4_masked(struct match *, ovs_be32 nshc4, ovs_be32 mask);
  990. +void match_set_encap_eth_src_masked(struct match *match, const struct eth_addr encap_eth_src, const struct eth_addr mask);
  991. +void match_set_encap_eth_dst_masked(struct match *match, const struct eth_addr encap_eth_dst, const struct eth_addr mask);
  992. +void match_set_encap_eth_type_masked(struct match *match, ovs_be16 encap_eth_type, ovs_be16 mask);
  993. +
  994. +void match_set_nsp(struct match *, ovs_be32 nsp);
  995. +void match_set_nsi(struct match *match, uint8_t nsi);
  996. +void match_set_nsh_mdtype(struct match *match, uint8_t nsh_mdtype);
  997. +void match_set_nsh_np(struct match *match, uint8_t nsh_np);
  998. +void match_set_nshc1(struct match *, ovs_be32 nshc1);
  999. +void match_set_nshc2(struct match *, ovs_be32 nshc2);
  1000. +void match_set_nshc3(struct match *, ovs_be32 nshc3);
  1001. +void match_set_nshc4(struct match *, ovs_be32 nshc4);
  1002. +void match_set_encap_eth_src(struct match *match, const struct eth_addr encap_eth_src);
  1003. +void match_set_encap_eth_dst(struct match *match, const struct eth_addr encap_eth_dst);
  1004. +void match_set_encap_eth_type(struct match *match, uint16_t encap_eth_type);
  1005. +
  1006. bool match_equal(const struct match *, const struct match *);
  1007. uint32_t match_hash(const struct match *, uint32_t basis);
  1008. diff --git a/lib/meta-flow.c b/lib/meta-flow.c
  1009. index ab77fca..648a753 100644
  1010. --- a/lib/meta-flow.c
  1011. +++ b/lib/meta-flow.c
  1012. @@ -243,7 +243,28 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
  1013. return !flow_get_xreg(&wc->masks, mf->id - MFF_XREG0);
  1014. case MFF_ACTSET_OUTPUT:
  1015. return !wc->masks.actset_output;
  1016. -
  1017. + case MFF_NSP:
  1018. + return !wc->masks.nsp;
  1019. + case MFF_NSI:
  1020. + return !wc->masks.nsi;
  1021. + case MFF_NSH_C1:
  1022. + return !wc->masks.nshc1;
  1023. + case MFF_NSH_C2:
  1024. + return !wc->masks.nshc2;
  1025. + case MFF_NSH_C3:
  1026. + return !wc->masks.nshc3;
  1027. + case MFF_NSH_C4:
  1028. + return !wc->masks.nshc4;
  1029. + case MFF_NSH_MDTYPE:
  1030. + return !wc->masks.nsh_mdtype;
  1031. + case MFF_NSH_NP:
  1032. + return !wc->masks.nsh_np;
  1033. + case MFF_ENCAP_ETH_SRC:
  1034. + return eth_addr_is_zero(wc->masks.encap_eth_src);
  1035. + case MFF_ENCAP_ETH_DST:
  1036. + return eth_addr_is_zero(wc->masks.encap_eth_dst);
  1037. + case MFF_ENCAP_ETH_TYPE:
  1038. + return !wc->masks.encap_eth_type;
  1039. case MFF_ETH_SRC:
  1040. return eth_addr_is_zero(wc->masks.dl_src);
  1041. case MFF_ETH_DST:
  1042. @@ -557,6 +578,17 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
  1043. case MFF_ICMPV6_TYPE:
  1044. case MFF_ICMPV6_CODE:
  1045. case MFF_ND_TARGET:
  1046. + case MFF_NSP:
  1047. + case MFF_NSI:
  1048. + case MFF_NSH_MDTYPE:
  1049. + case MFF_NSH_NP:
  1050. + case MFF_NSH_C1:
  1051. + case MFF_NSH_C2:
  1052. + case MFF_NSH_C3:
  1053. + case MFF_NSH_C4:
  1054. + case MFF_ENCAP_ETH_SRC:
  1055. + case MFF_ENCAP_ETH_DST:
  1056. + case MFF_ENCAP_ETH_TYPE:
  1057. case MFF_ND_SLL:
  1058. case MFF_ND_TLL:
  1059. return true;
  1060. @@ -716,6 +748,50 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
  1061. value->be64 = htonll(flow_get_xreg(flow, mf->id - MFF_XREG0));
  1062. break;
  1063. + case MFF_NSP:
  1064. + value->be32 = flow->nsp;
  1065. + break;
  1066. +
  1067. + case MFF_NSI:
  1068. + value->u8 = flow->nsi;
  1069. + break;
  1070. +
  1071. + case MFF_NSH_C1:
  1072. + value->be32 = flow->nshc1;
  1073. + break;
  1074. +
  1075. + case MFF_NSH_C2:
  1076. + value->be32 = flow->nshc2;
  1077. + break;
  1078. +
  1079. + case MFF_NSH_C3:
  1080. + value->be32 = flow->nshc3;
  1081. + break;
  1082. +
  1083. + case MFF_NSH_C4:
  1084. + value->be32 = flow->nshc4;
  1085. + break;
  1086. +
  1087. + case MFF_NSH_MDTYPE:
  1088. + value->u8 = flow->nsh_mdtype;
  1089. + break;
  1090. +
  1091. + case MFF_NSH_NP:
  1092. + value->u8 = flow->nsh_np;
  1093. + break;
  1094. +
  1095. + case MFF_ENCAP_ETH_SRC:
  1096. + value->mac = flow->encap_eth_src;
  1097. + break;
  1098. +
  1099. + case MFF_ENCAP_ETH_DST:
  1100. + value->mac = flow->encap_eth_dst;
  1101. + break;
  1102. +
  1103. + case MFF_ENCAP_ETH_TYPE:
  1104. + value->be16 = flow->encap_eth_type;
  1105. + break;
  1106. +
  1107. case MFF_ETH_SRC:
  1108. value->mac = flow->dl_src;
  1109. break;
  1110. @@ -1085,6 +1161,50 @@ mf_set_value(const struct mf_field *mf,
  1111. match_set_arp_sha(match, value->mac);
  1112. break;
  1113. + case MFF_NSP:
  1114. + match_set_nsp(match, value->be32);
  1115. + break;
  1116. +
  1117. + case MFF_NSI:
  1118. + match_set_nsi(match, value->u8);
  1119. + break;
  1120. +
  1121. + case MFF_NSH_MDTYPE:
  1122. + match_set_nsh_mdtype(match, value->u8);
  1123. + break;
  1124. +
  1125. + case MFF_NSH_NP:
  1126. + match_set_nsh_np(match, value->u8);
  1127. + break;
  1128. +
  1129. + case MFF_NSH_C1:
  1130. + match_set_nshc1(match, value->be32);
  1131. + break;
  1132. +
  1133. + case MFF_NSH_C2:
  1134. + match_set_nshc2(match, value->be32);
  1135. + break;
  1136. +
  1137. + case MFF_NSH_C3:
  1138. + match_set_nshc3(match, value->be32);
  1139. + break;
  1140. +
  1141. + case MFF_NSH_C4:
  1142. + match_set_nshc4(match, value->be32);
  1143. + break;
  1144. +
  1145. + case MFF_ENCAP_ETH_SRC:
  1146. + match_set_encap_eth_src(match, value->mac);
  1147. + break;
  1148. +
  1149. + case MFF_ENCAP_ETH_DST:
  1150. + match_set_encap_eth_dst(match, value->mac);
  1151. + break;
  1152. +
  1153. + case MFF_ENCAP_ETH_TYPE:
  1154. + match_set_encap_eth_type(match, value->be16);
  1155. + break;
  1156. +
  1157. case MFF_ARP_THA:
  1158. case MFF_ND_TLL:
  1159. match_set_arp_tha(match, value->mac);
  1160. @@ -1296,6 +1416,50 @@ mf_set_flow_value(const struct mf_field *mf,
  1161. flow_set_xreg(flow, mf->id - MFF_XREG0, ntohll(value->be64));
  1162. break;
  1163. + case MFF_NSP:
  1164. + flow->nsp = value->be32;
  1165. + break;
  1166. +
  1167. + case MFF_NSI:
  1168. + flow->nsi = value->u8;
  1169. + break;
  1170. +
  1171. + case MFF_NSH_C1:
  1172. + flow->nshc1 = value->be32;
  1173. + break;
  1174. +
  1175. + case MFF_NSH_C2:
  1176. + flow->nshc2 = value->be32;
  1177. + break;
  1178. +
  1179. + case MFF_NSH_C3:
  1180. + flow->nshc3 = value->be32;
  1181. + break;
  1182. +
  1183. + case MFF_NSH_C4:
  1184. + flow->nshc4 = value->be32;
  1185. + break;
  1186. +
  1187. + case MFF_NSH_MDTYPE:
  1188. + flow->nsh_mdtype = value->u8;
  1189. + break;
  1190. +
  1191. + case MFF_NSH_NP:
  1192. + flow->nsh_np = value->u8;
  1193. + break;
  1194. +
  1195. + case MFF_ENCAP_ETH_SRC:
  1196. + flow->encap_eth_src = value->mac;
  1197. + break;
  1198. +
  1199. + case MFF_ENCAP_ETH_DST:
  1200. + flow->encap_eth_dst = value->mac;
  1201. + break;
  1202. +
  1203. + case MFF_ENCAP_ETH_TYPE:
  1204. + flow->encap_eth_type = value->be16;
  1205. + break;
  1206. +
  1207. case MFF_ETH_SRC:
  1208. flow->dl_src = value->mac;
  1209. break;
  1210. @@ -1734,6 +1898,52 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
  1211. match->wc.masks.arp_sha = eth_addr_zero;
  1212. break;
  1213. + case MFF_NSP:
  1214. + match_set_nsp_masked(match, htonl(0), htonl(0));
  1215. + break;
  1216. +
  1217. + case MFF_NSI:
  1218. + match_set_nsi_masked(match, 0, 0);
  1219. + break;
  1220. +
  1221. + case MFF_NSH_MDTYPE:
  1222. + match_set_nsh_mdtype_masked(match, 0, 0);
  1223. + break;
  1224. +
  1225. + case MFF_NSH_NP:
  1226. + match_set_nsh_np_masked(match, 0, 0);
  1227. + break;
  1228. +
  1229. + case MFF_NSH_C1:
  1230. + match_set_nshc1_masked(match, htonl(0), htonl(0));
  1231. + break;
  1232. +
  1233. + case MFF_NSH_C2:
  1234. + match_set_nshc2_masked(match, htonl(0), htonl(0));
  1235. + break;
  1236. +
  1237. + case MFF_NSH_C3:
  1238. + match_set_nshc3_masked(match, htonl(0), htonl(0));
  1239. + break;
  1240. +
  1241. + case MFF_NSH_C4:
  1242. + match_set_nshc4_masked(match, htonl(0), htonl(0));
  1243. + break;
  1244. +
  1245. + case MFF_ENCAP_ETH_SRC:
  1246. + match->flow.encap_eth_src= eth_addr_zero;
  1247. + match->wc.masks.encap_eth_src = eth_addr_zero;
  1248. + break;
  1249. +
  1250. + case MFF_ENCAP_ETH_DST:
  1251. + match->flow.encap_eth_dst= eth_addr_zero;
  1252. + match->wc.masks.encap_eth_dst = eth_addr_zero;
  1253. + break;
  1254. +
  1255. + case MFF_ENCAP_ETH_TYPE:
  1256. + match_set_encap_eth_type_masked(match, htons(0), htons(0));
  1257. + break;
  1258. +
  1259. case MFF_ARP_THA:
  1260. case MFF_ND_TLL:
  1261. match->flow.arp_tha = eth_addr_zero;
  1262. @@ -1929,6 +2139,50 @@ mf_set(const struct mf_field *mf,
  1263. match_set_arp_sha_masked(match, value->mac, mask->mac);
  1264. break;
  1265. + case MFF_NSP:
  1266. + match_set_nsp_masked(match, value->be32, mask->be32);
  1267. + break;
  1268. +
  1269. + case MFF_NSI:
  1270. + match_set_nsi_masked(match, value->u8, mask->u8);
  1271. + break;
  1272. +
  1273. + case MFF_NSH_MDTYPE:
  1274. + match_set_nsh_mdtype_masked(match, value->u8, mask->u8);
  1275. + break;
  1276. +
  1277. + case MFF_NSH_NP:
  1278. + match_set_nsh_np_masked(match, value->u8, mask->u8);
  1279. + break;
  1280. +
  1281. + case MFF_NSH_C1:
  1282. + match_set_nshc1_masked(match, value->be32, mask->be32);
  1283. + break;
  1284. +
  1285. + case MFF_NSH_C2:
  1286. + match_set_nshc2_masked(match, value->be32, mask->be32);
  1287. + break;
  1288. +
  1289. + case MFF_NSH_C3:
  1290. + match_set_nshc3_masked(match, value->be32, mask->be32);
  1291. + break;
  1292. +
  1293. + case MFF_NSH_C4:
  1294. + match_set_nshc4_masked(match, value->be32, mask->be32);
  1295. + break;
  1296. +
  1297. + case MFF_ENCAP_ETH_SRC:
  1298. + match_set_encap_eth_src_masked(match, value->mac, mask->mac);
  1299. + break;
  1300. +
  1301. + case MFF_ENCAP_ETH_DST:
  1302. + match_set_encap_eth_dst_masked(match, value->mac, mask->mac);
  1303. + break;
  1304. +
  1305. + case MFF_ENCAP_ETH_TYPE:
  1306. + match_set_encap_eth_type_masked(match, value->be16, mask->be16);
  1307. + break;
  1308. +
  1309. case MFF_ARP_THA:
  1310. case MFF_ND_TLL:
  1311. match_set_arp_tha_masked(match, value->mac, mask->mac);
  1312. diff --git a/lib/meta-flow.h b/lib/meta-flow.h
  1313. index 4bd9ff6..a226b79 100644
  1314. --- a/lib/meta-flow.h
  1315. +++ b/lib/meta-flow.h
  1316. @@ -1747,6 +1747,180 @@ enum OVS_PACKED_ENUM mf_field_id {
  1317. */
  1318. MFF_ND_TLL,
  1319. + /* "nsp".
  1320. + *
  1321. + * For a packet received including a (32-bit)
  1322. + * network service header service path (nsp), the nsp is stored
  1323. + * in the low 24-bits and the high bits are zeroed. For
  1324. + * other packets, the value is 0.
  1325. + *
  1326. + * Type: be32.
  1327. + * Maskable: bitwise.
  1328. + * Formatting: hexadecimal.
  1329. + * Prerequisites: none.
  1330. + * Access: read/write.
  1331. + * NXM: NXM_NX_NSP(113) since v1.1.
  1332. + * OXM: none.
  1333. + * Prefix lookup member: nsp.
  1334. + */
  1335. + MFF_NSP,
  1336. +
  1337. + /* "nsi".
  1338. + *
  1339. + * For a packet received, it includes a (8-bit)
  1340. + * network service header service index (nsi).
  1341. + *
  1342. + * Type: u8.
  1343. + * Maskable: bitwise.
  1344. + * Formatting: decimal.
  1345. + * Prerequisites: none.
  1346. + * Access: read/write.
  1347. + * NXM: NXM_NX_NSI(114) since v1.1.
  1348. + * OXM: none.
  1349. + * Prefix lookup member: nsi.
  1350. + */
  1351. + MFF_NSI,
  1352. +
  1353. + /* "nshc1".
  1354. + *
  1355. + * For a packet received including a (32-bit)
  1356. + * Network Platform Context (nshc1), the nshc1 is stored
  1357. + * in the 32-bits. For other packets, the value is 0.
  1358. + *
  1359. + * Type: be32.
  1360. + * Maskable: bitwise.
  1361. + * Formatting: hexadecimal.
  1362. + * Prerequisites: none.
  1363. + * Access: read/write.
  1364. + * NXM: NXM_NX_NSH_C1(115) since v1.1.
  1365. + * OXM: none.
  1366. + * Prefix lookup member: nshc1.
  1367. + */
  1368. + MFF_NSH_C1,
  1369. +
  1370. + /* "nshc2".
  1371. + *
  1372. + * For a packet received including a (32-bit)
  1373. + * Network Shared Context (nshc2), the nshc2 is stored
  1374. + * in the 32-bits. For other packets, the value is 0.
  1375. + *
  1376. + * Type: be32.
  1377. + * Maskable: bitwise.
  1378. + * Formatting: hexadecimal.
  1379. + * Prerequisites: none.
  1380. + * Access: read/write.
  1381. + * NXM: NXM_NX_NSH_C2(116) since v1.1.
  1382. + * OXM: none.
  1383. + * Prefix lookup member: nshc2.
  1384. + */
  1385. + MFF_NSH_C2,
  1386. +
  1387. + /* "nshc3".
  1388. + *
  1389. + * For a packet received via including a (32-bit)
  1390. + * Service Platform Context (nshc3), the nshc3 is stored
  1391. + * in the 32-bits. For other packets, the value is 0.
  1392. + *
  1393. + * Type: be32.
  1394. + * Maskable: bitwise.
  1395. + * Formatting: hexadecimal.
  1396. + * Prerequisites: none.
  1397. + * Access: read/write.
  1398. + * NXM: NXM_NX_NSH_C3(117) since v1.1.
  1399. + * OXM: none.
  1400. + * Prefix lookup member: nshc3.
  1401. + */
  1402. + MFF_NSH_C3,
  1403. +
  1404. + /* "nshc4".
  1405. + *
  1406. + * For a packet received including a (32-bit)
  1407. + * Service Shared Context (nshc4), the nshc4 is stored
  1408. + * in the 32-bits. For other packets, the value is 0.
  1409. + *
  1410. + * Type: be32.
  1411. + * Maskable: bitwise.
  1412. + * Formatting: hexadecimal.
  1413. + * Prerequisites: none.
  1414. + * Access: read/write.
  1415. + * NXM: NXM_NX_NSH_C4(118) since v1.1.
  1416. + * OXM: none.
  1417. + * Prefix lookup member: nshc4.
  1418. + */
  1419. + MFF_NSH_C4,
  1420. +
  1421. + /* "nsh_mdtype".
  1422. + *
  1423. + * For a packet received, it includes a (8-bit)
  1424. + * nsh md-type field (md-type).
  1425. + *
  1426. + * Type: u8.
  1427. + * Maskable: bitwise.
  1428. + * Formatting: decimal.
  1429. + * Prerequisites: none.
  1430. + * Access: read/write.
  1431. + * NXM: NXM_NX_NSH_MDTYPE(119) since v1.1.
  1432. + * OXM: none.
  1433. + */
  1434. + MFF_NSH_MDTYPE,
  1435. +
  1436. + /* "nsh_np".
  1437. + *
  1438. + * For a packet received, it includes a (8-bit)
  1439. + * nsh next protocol field (np).
  1440. + *
  1441. + * Type: u8.
  1442. + * Maskable: bitwise.
  1443. + * Formatting: decimal.
  1444. + * Prerequisites: none.
  1445. + * Access: read/write.
  1446. + * NXM: NXM_NX_NSH_NP(120) since v1.1.
  1447. + * OXM: none.
  1448. + */
  1449. + MFF_NSH_NP,
  1450. +
  1451. + /* "encap_eth_src".
  1452. + *
  1453. + * encap eth source address for Ethernet+NSH
  1454. + *
  1455. + * Type: MAC.
  1456. + * Maskable: bitwise.
  1457. + * Formatting: Ethernet.
  1458. + * Prerequisites: none.
  1459. + * Access: read/write.
  1460. + * NXM: NXM_NX_ENCAP_ETH_SRC(121) since v1.1.
  1461. + * OXM: none.
  1462. + */
  1463. + MFF_ENCAP_ETH_SRC,
  1464. +
  1465. + /* "encap_eth_dst".
  1466. + *
  1467. + * encap eth destination address for Ethernet+NSH
  1468. + *
  1469. + * Type: MAC.
  1470. + * Maskable: bitwise.
  1471. + * Formatting: Ethernet.
  1472. + * Prerequisites: none.
  1473. + * Access: read/write.
  1474. + * NXM: NXM_NX_ENCAP_ETH_DST(122) since v1.1.
  1475. + * OXM: none.
  1476. + */
  1477. + MFF_ENCAP_ETH_DST,
  1478. +
  1479. + /* "encap_eth_type".
  1480. + *
  1481. + * Encap Ethernet type.
  1482. + *
  1483. + * Type: be16.
  1484. + * Maskable: no.
  1485. + * Formatting: hexadecimal.
  1486. + * Prerequisites: none.
  1487. + * Access: read/write.
  1488. + * NXM: NXM_NX_ENCAP_ETH_TYPE(123) since v1.1.
  1489. + * OXM: none.
  1490. + */
  1491. + MFF_ENCAP_ETH_TYPE,
  1492. +
  1493. MFF_N_IDS
  1494. };
  1495. diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
  1496. index 92ceec1..406a492 100644
  1497. --- a/lib/netdev-vport.c
  1498. +++ b/lib/netdev-vport.c
  1499. @@ -582,9 +582,15 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
  1500. ext = strtok_r(str, ",", &save_ptr);
  1501. while (ext) {
  1502. if (!strcmp(type, "vxlan") && !strcmp(ext, "gbp")) {
  1503. - tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
  1504. + if (tnl_cfg.exts & (1 << OVS_VXLAN_EXT_GPE))
  1505. + VLOG_WARN("VXLAN_GPE extension exists, VxLAN_GBP extension can't be added.");
  1506. + else
  1507. + tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
  1508. } else if (!strcmp(type, "vxlan") && !strcmp(ext, "gpe")) {
  1509. - tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GPE);
  1510. + if (tnl_cfg.exts & (1 << OVS_VXLAN_EXT_GBP))
  1511. + VLOG_WARN("VXLAN_GBP extension exists, VxLAN_GPE extension can't be added.");
  1512. + else
  1513. + tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GPE);
  1514. } else {
  1515. VLOG_WARN("%s: unknown extension '%s'", name, ext);
  1516. }
  1517. diff --git a/lib/nx-match.c b/lib/nx-match.c
  1518. index 0eecac7..8d2bc4b 100644
  1519. --- a/lib/nx-match.c
  1520. +++ b/lib/nx-match.c
  1521. @@ -949,6 +949,25 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
  1522. ofputil_port_to_ofp11(flow->actset_output));
  1523. }
  1524. + /* NSH */
  1525. + nxm_put_32m(b, MFF_NSP, oxm, flow->nsp, match->wc.masks.nsp);
  1526. + nxm_put_8m(b, MFF_NSI, oxm, flow->nsi, match->wc.masks.nsi);
  1527. + nxm_put_8m(b, MFF_NSH_MDTYPE, oxm, flow->nsh_mdtype, match->wc.masks.nsh_mdtype);
  1528. + nxm_put_8m(b, MFF_NSH_NP, oxm, flow->nsh_np, match->wc.masks.nsh_np);
  1529. + nxm_put_32m(b, MFF_NSH_C1, oxm, flow->nshc1, match->wc.masks.nshc1);
  1530. + nxm_put_32m(b, MFF_NSH_C2, oxm, flow->nshc2, match->wc.masks.nshc2);
  1531. + nxm_put_32m(b, MFF_NSH_C3, oxm, flow->nshc3, match->wc.masks.nshc3);
  1532. + nxm_put_32m(b, MFF_NSH_C4, oxm, flow->nshc4, match->wc.masks.nshc4);
  1533. +
  1534. + /* ENCAP Eth */
  1535. + nxm_put_eth_masked(b, MFF_ENCAP_ETH_SRC, oxm,
  1536. + flow->encap_eth_src, match->wc.masks.encap_eth_src);
  1537. + nxm_put_eth_masked(b, MFF_ENCAP_ETH_DST, oxm,
  1538. + flow->encap_eth_dst, match->wc.masks.encap_eth_dst);
  1539. + nxm_put_16m(b, MFF_ENCAP_ETH_TYPE, oxm,
  1540. + ofputil_dl_type_to_openflow(flow->encap_eth_type),
  1541. + match->wc.masks.encap_eth_type); //uncertain
  1542. +
  1543. /* Ethernet. */
  1544. nxm_put_eth_masked(b, MFF_ETH_SRC, oxm,
  1545. flow->dl_src, match->wc.masks.dl_src);
  1546. diff --git a/lib/odp-execute.c b/lib/odp-execute.c
  1547. index b5204b2..b6dcd98 100644
  1548. --- a/lib/odp-execute.c
  1549. +++ b/lib/odp-execute.c
  1550. @@ -434,6 +434,8 @@ odp_execute_masked_set_action(struct dp_packet *packet,
  1551. case OVS_KEY_ATTR_ETHERTYPE:
  1552. case OVS_KEY_ATTR_IN_PORT:
  1553. case OVS_KEY_ATTR_VLAN:
  1554. + case OVS_KEY_ATTR_NSH:
  1555. + case OVS_KEY_ATTR_ENCAP_ETH:
  1556. case OVS_KEY_ATTR_ICMP:
  1557. case OVS_KEY_ATTR_ICMPV6:
  1558. case OVS_KEY_ATTR_TCP_FLAGS:
  1559. @@ -497,6 +499,10 @@ requires_datapath_assistance(const struct nlattr *a)
  1560. case OVS_ACTION_ATTR_SET:
  1561. case OVS_ACTION_ATTR_SET_MASKED:
  1562. + case OVS_ACTION_ATTR_PUSH_NSH:
  1563. + case OVS_ACTION_ATTR_POP_NSH:
  1564. + case OVS_ACTION_ATTR_PUSH_ETH:
  1565. + case OVS_ACTION_ATTR_POP_ETH:
  1566. case OVS_ACTION_ATTR_PUSH_VLAN:
  1567. case OVS_ACTION_ATTR_POP_VLAN:
  1568. case OVS_ACTION_ATTR_SAMPLE:
  1569. @@ -623,6 +629,10 @@ odp_execute_actions(void *dp, struct dp_packet **packets, int cnt, bool steal,
  1570. }
  1571. break;
  1572. + case OVS_ACTION_ATTR_PUSH_NSH:
  1573. + case OVS_ACTION_ATTR_POP_NSH:
  1574. + case OVS_ACTION_ATTR_PUSH_ETH:
  1575. + case OVS_ACTION_ATTR_POP_ETH:
  1576. case OVS_ACTION_ATTR_OUTPUT:
  1577. case OVS_ACTION_ATTR_TUNNEL_PUSH:
  1578. case OVS_ACTION_ATTR_TUNNEL_POP:
  1579. diff --git a/lib/odp-util.c b/lib/odp-util.c
  1580. index 7983720..102dfd7 100644
  1581. --- a/lib/odp-util.c
  1582. +++ b/lib/odp-util.c
  1583. @@ -70,7 +70,8 @@ static void format_odp_key_attr(const struct nlattr *a,
  1584. const struct nlattr *ma,
  1585. const struct hmap *portno_names, struct ds *ds,
  1586. bool verbose);
  1587. -
  1588. +static void format_eth(struct ds *ds, const char *name, const struct eth_addr key,
  1589. + const struct eth_addr *mask, bool verbose);
  1590. struct geneve_scan {
  1591. struct geneve_opt d[63];
  1592. int len;
  1593. @@ -112,6 +113,10 @@ odp_action_len(uint16_t type)
  1594. case OVS_ACTION_ATTR_USERSPACE: return ATTR_LEN_VARIABLE;
  1595. case OVS_ACTION_ATTR_PUSH_VLAN: return sizeof(struct ovs_action_push_vlan);
  1596. case OVS_ACTION_ATTR_POP_VLAN: return 0;
  1597. + case OVS_ACTION_ATTR_PUSH_NSH: return sizeof(struct ovs_action_push_nsh);
  1598. + case OVS_ACTION_ATTR_POP_NSH: return 0;
  1599. + case OVS_ACTION_ATTR_PUSH_ETH: return sizeof(struct ovs_action_push_eth);
  1600. + case OVS_ACTION_ATTR_POP_ETH: return 0;
  1601. case OVS_ACTION_ATTR_PUSH_MPLS: return sizeof(struct ovs_action_push_mpls);
  1602. case OVS_ACTION_ATTR_POP_MPLS: return sizeof(ovs_be16);
  1603. case OVS_ACTION_ATTR_RECIRC: return sizeof(uint32_t);
  1604. @@ -147,6 +152,8 @@ ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize)
  1605. case OVS_KEY_ATTR_CT_LABELS: return "ct_label";
  1606. case OVS_KEY_ATTR_TUNNEL: return "tunnel";
  1607. case OVS_KEY_ATTR_IN_PORT: return "in_port";
  1608. + case OVS_KEY_ATTR_ENCAP_ETH: return "encap_eth";
  1609. + case OVS_KEY_ATTR_NSH: return "nsh";
  1610. case OVS_KEY_ATTR_ETHERNET: return "eth";
  1611. case OVS_KEY_ATTR_VLAN: return "vlan";
  1612. case OVS_KEY_ATTR_ETHERTYPE: return "eth_type";
  1613. @@ -373,6 +380,36 @@ format_vlan_tci(struct ds *ds, ovs_be16 tci, ovs_be16 mask, bool verbose)
  1614. }
  1615. static void
  1616. +format_nsh(struct ds *ds, const struct ovs_action_push_nsh * nsh)
  1617. +{
  1618. + const struct nsh_hdr *nsh_hdr =(struct nsh_hdr *)nsh->header;
  1619. + ds_put_format(ds, "nsh_mdtype=%"PRIu8",nsh_np=%"PRIu8",nsp=%"PRIu32
  1620. + ",nsi=%"PRIu8",nshc1=%"PRIu32",nshc2=%"PRIu32
  1621. + ",nshc3=%"PRIu32",nshc4=%"PRIu32")",
  1622. + nsh_hdr->base.mdtype,
  1623. + nsh_hdr->base.proto,
  1624. + ntohl(nsh_hdr->base.path_hdr << 8),
  1625. + ntohl(nsh_hdr->base.path_hdr >> 24),
  1626. + ntohl(nsh_hdr->ctx.nshc1),
  1627. + ntohl(nsh_hdr->ctx.nshc2),
  1628. + ntohl(nsh_hdr->ctx.nshc3),
  1629. + ntohl(nsh_hdr->ctx.nshc4));
  1630. +}
  1631. +
  1632. +static void
  1633. +format_encap_eth(struct ds *ds, const struct ovs_action_push_eth *encap_eth)
  1634. +{
  1635. + const struct encap_eth_hdr *encap_eth_hdr = (struct encap_eth_hdr *)encap_eth->header;
  1636. + ds_put_format(ds, "encap_eth_type=%"PRIu16",",
  1637. + ntohs(encap_eth_hdr->encap_eth_type));
  1638. + format_eth(ds, "encap_eth_src", encap_eth_hdr->encap_eth_src,
  1639. + NULL, true);
  1640. + format_eth(ds, "encap_eth_dst", encap_eth_hdr->encap_eth_dst,
  1641. + NULL, true);
  1642. + ds_put_format(ds, ")");
  1643. +}
  1644. +
  1645. +static void
  1646. format_mpls_lse(struct ds *ds, ovs_be32 mpls_lse)
  1647. {
  1648. ds_put_format(ds, "label=%"PRIu32",tc=%d,ttl=%d,bos=%d",
  1649. @@ -500,7 +537,7 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
  1650. gnh->oam ? "oam," : "",
  1651. gnh->critical ? "crit," : "",
  1652. ntohl(get_16aligned_be32(&gnh->vni)) >> 8);
  1653. -
  1654. +
  1655. if (gnh->opt_len) {
  1656. ds_put_cstr(ds, ",options(");
  1657. format_geneve_opts(gnh->options, NULL, gnh->opt_len * 4,
  1658. @@ -760,6 +797,8 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
  1659. {
  1660. int expected_len;
  1661. enum ovs_action_attr type = nl_attr_type(a);
  1662. + const struct ovs_action_push_nsh *nsh;
  1663. + const struct ovs_action_push_eth *encap_eth;
  1664. size_t size;
  1665. expected_len = odp_action_len(nl_attr_type(a));
  1666. @@ -830,6 +869,23 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
  1667. case OVS_ACTION_ATTR_POP_VLAN:
  1668. ds_put_cstr(ds, "pop_vlan");
  1669. break;
  1670. + case OVS_ACTION_ATTR_PUSH_NSH:
  1671. + nsh = nl_attr_get(a);
  1672. + ds_put_cstr(ds, "push_nsh(");
  1673. + format_nsh(ds, nsh);
  1674. + break;
  1675. + case OVS_ACTION_ATTR_POP_NSH:
  1676. + ds_put_cstr(ds, "pop_nsh");
  1677. + break;
  1678. +
  1679. + case OVS_ACTION_ATTR_PUSH_ETH:
  1680. + encap_eth = nl_attr_get(a);
  1681. + ds_put_cstr(ds, "push_eth(");
  1682. + format_encap_eth(ds, encap_eth);
  1683. + break;
  1684. + case OVS_ACTION_ATTR_POP_ETH:
  1685. + ds_put_cstr(ds, "pop_eth");
  1686. + break;
  1687. case OVS_ACTION_ATTR_PUSH_MPLS: {
  1688. const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
  1689. ds_put_cstr(ds, "push_mpls(");
  1690. @@ -1618,6 +1674,72 @@ parse_odp_action(const char *s, const struct simap *port_names,
  1691. }
  1692. {
  1693. + struct ovs_action_push_nsh push;
  1694. + struct nsh_hdr *nsh = (struct nsh_hdr *)push.header;
  1695. + ovs_be32 nsp, nshc1,nshc2,nshc3,nshc4;
  1696. + uint8_t nsi, nsh_mdtype, nsh_np;
  1697. + int n = -1;
  1698. +
  1699. + if (ovs_scan_len(s, &n, "push_nsh(nsh_mdtype=%"SCNi8",nsh_np=%"SCNi8",nsp=0x%"SCNx32
  1700. + ",nsi=%"SCNi8",nshc1=0x%"SCNx32",nshc2=0x%"SCNx32
  1701. + ",nshc3=0x%"SCNx32",nshc4=0x%"SCNx32"))",
  1702. + &nsh_mdtype, &nsh_np,
  1703. + &nsp, &nsi,
  1704. + &nshc1, &nshc2,
  1705. + &nshc3, &nshc4)) {
  1706. + if (nsh_mdtype == NSH_M_TYPE1) {
  1707. + nsh->base.mdtype = NSH_M_TYPE1;
  1708. + nsh->base.version = 0x01;
  1709. + nsh->base.length = 6;
  1710. + nsh->base.proto = nsh_np;
  1711. + nsh->base.path_hdr= nsp;
  1712. + nsh->base.svc_idx = nsi;
  1713. + nsh->ctx.nshc1=nshc1;
  1714. + nsh->ctx.nshc2=nshc2;
  1715. + nsh->ctx.nshc3=nshc3;
  1716. + nsh->ctx.nshc4=nshc4;
  1717. + push.nsh_mdtype = NSH_M_TYPE1;
  1718. + nl_msg_put_unspec(actions, OVS_ACTION_ATTR_PUSH_NSH,
  1719. + &push, sizeof push);
  1720. + }
  1721. +
  1722. + return n;
  1723. + }
  1724. + }
  1725. +
  1726. + if (!strncmp(s, "pop_nsh", 7)) {
  1727. + nl_msg_put_flag(actions, OVS_ACTION_ATTR_POP_NSH);
  1728. + return 7;
  1729. + }
  1730. +
  1731. + {
  1732. + struct ovs_action_push_eth push;
  1733. + struct encap_eth_hdr *encap_eth = (struct encap_eth_hdr *)push.header;
  1734. + uint16_t encap_eth_type;
  1735. + int n = -1;
  1736. +
  1737. + if (ovs_scan_len(s, &n, "push_eth(encap_eth_type=0x%"SCNx16",encap_eth_dst="ETH_ADDR_SCAN_FMT",encap_eth_src="ETH_ADDR_SCAN_FMT")",
  1738. + &encap_eth_type,
  1739. + ETH_ADDR_SCAN_ARGS(encap_eth->encap_eth_dst),
  1740. + ETH_ADDR_SCAN_ARGS(encap_eth->encap_eth_src))) {
  1741. + if (encap_eth->encap_eth_type == ETH_P_NSH) {
  1742. + push.encap_eth_type = ETH_P_NSH;
  1743. + encap_eth->encap_eth_type = htons(ETH_P_NSH);
  1744. + nl_msg_put_unspec(actions, OVS_ACTION_ATTR_PUSH_ETH,
  1745. + &push, sizeof push);
  1746. + }
  1747. +
  1748. + return n;
  1749. + }
  1750. +
  1751. + }
  1752. +
  1753. + if (!strncmp(s, "pop_eth", 7)) {
  1754. + nl_msg_put_flag(actions, OVS_ACTION_ATTR_POP_ETH);
  1755. + return 7;
  1756. + }
  1757. +
  1758. + {
  1759. double percentage;
  1760. int n = -1;
  1761. @@ -1759,6 +1881,8 @@ static const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] =
  1762. .next = ovs_tun_key_attr_lens,
  1763. .next_max = OVS_TUNNEL_KEY_ATTR_MAX },
  1764. [OVS_KEY_ATTR_IN_PORT] = { .len = 4 },
  1765. + [OVS_KEY_ATTR_ENCAP_ETH] = { .len = 14 },
  1766. + [OVS_KEY_ATTR_NSH] = { .len = 24 },
  1767. [OVS_KEY_ATTR_ETHERNET] = { .len = sizeof(struct ovs_key_ethernet) },
  1768. [OVS_KEY_ATTR_VLAN] = { .len = 2 },
  1769. [OVS_KEY_ATTR_ETHERTYPE] = { .len = 2 },
  1770. @@ -2146,6 +2270,23 @@ format_be64(struct ds *ds, const char *name, ovs_be64 key,
  1771. }
  1772. static void
  1773. +format_be32(struct ds *ds, const char *name, ovs_be32 key,
  1774. + const ovs_be32 *mask, bool verbose)
  1775. +{
  1776. + bool mask_empty = mask && !*mask;
  1777. +
  1778. + if (verbose || !mask_empty) {
  1779. + bool mask_full = !mask || *mask == OVS_BE32_MAX;
  1780. +
  1781. + ds_put_format(ds, "%s=%"PRIx32, name, ntohl(key));
  1782. + if (!mask_full) { /* Partially masked. */
  1783. + ds_put_format(ds, "/%#"PRIx32, ntohl(*mask));
  1784. + }
  1785. + ds_put_char(ds, ',');
  1786. + }
  1787. +}
  1788. +
  1789. +static void
  1790. format_ipv4(struct ds *ds, const char *name, ovs_be32 key,
  1791. const ovs_be32 *mask, bool verbose)
  1792. {
  1793. @@ -2798,6 +2939,34 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
  1794. }
  1795. break;
  1796. + case OVS_KEY_ATTR_NSH: {
  1797. + const struct ovs_key_nsh *mask = ma ? nl_attr_get(ma) : NULL;
  1798. + const struct ovs_key_nsh *key = nl_attr_get(a);
  1799. +
  1800. + format_u8u(ds, "nsi", key->nsi, MASK(mask, nsi), verbose);
  1801. + format_be32(ds, "nsp", key->nsp, MASK(mask, nsp), verbose);
  1802. + format_u8u(ds, "nsh_mdtype", key->nsh_mdtype, MASK(mask, nsh_mdtype), verbose);
  1803. + format_u8u(ds, "nsh_np", key->nsh_np, MASK(mask, nsh_np), verbose);
  1804. + format_be32(ds, "nshc1", key->nshc1, MASK(mask, nshc1), verbose);
  1805. + format_be32(ds, "nshc2", key->nshc2, MASK(mask, nshc2), verbose);
  1806. + format_be32(ds, "nshc3", key->nshc3, MASK(mask, nshc3), verbose);
  1807. + format_be32(ds, "nshc4", key->nshc4, MASK(mask, nshc4), verbose);
  1808. + ds_chomp(ds, ',');
  1809. + break;
  1810. + }
  1811. +
  1812. + case OVS_KEY_ATTR_ENCAP_ETH: {
  1813. + const struct ovs_key_encap_eth *mask = ma ? nl_attr_get(ma) : NULL;
  1814. + const struct ovs_key_encap_eth *key = nl_attr_get(a);
  1815. +
  1816. + format_be16(ds, "encap_eth_type", key->encap_eth_type, MASK(mask, encap_eth_type), verbose);
  1817. + format_eth(ds, "encap_eth_src", key->encap_eth_src, MASK(mask, encap_eth_src), verbose);
  1818. + format_eth(ds, "encap_eth_dst", key->encap_eth_dst, MASK(mask, encap_eth_dst), verbose);
  1819. + ds_chomp(ds, ',');
  1820. +
  1821. + break;
  1822. + }
  1823. +
  1824. case OVS_KEY_ATTR_ETHERNET: {
  1825. const struct ovs_key_ethernet *mask = ma ? nl_attr_get(ma) : NULL;
  1826. const struct ovs_key_ethernet *key = nl_attr_get(a);
  1827. @@ -3184,6 +3353,48 @@ scan_eth(const char *s, struct eth_addr *key, struct eth_addr *mask)
  1828. }
  1829. static int
  1830. +scan_nsp(const char *s, uint32_t *key, uint32_t *mask)
  1831. +{
  1832. + int n;
  1833. +
  1834. + if (ovs_scan(s, "%"SCNi32"%n", key, &n)) {
  1835. + int len = n;
  1836. + *key = htonl(*key);
  1837. + if (mask) {
  1838. + if (ovs_scan(s + len, "/%"SCNi32"%n", mask, &n)) {
  1839. + len += n;
  1840. + *mask =htonl(*mask);
  1841. + } else {
  1842. + *mask = UINT32_MAX;
  1843. + }
  1844. + }
  1845. + return len;
  1846. + }
  1847. + return 0;
  1848. +}
  1849. +
  1850. +static int
  1851. +scan_encap_eth_type(const char *s, uint16_t *key, uint16_t *mask)
  1852. +{
  1853. + int n;
  1854. +
  1855. + if (ovs_scan(s, "%"SCNi16"%n", key, &n)) {
  1856. + int len = n;
  1857. + *key = htons(*key);
  1858. + if (mask) {
  1859. + if (ovs_scan(s + len, "/%"SCNi16"%n", mask, &n)) {
  1860. + len += n;
  1861. + *mask = htons(*mask);
  1862. + } else {
  1863. + *mask = UINT16_MAX;
  1864. + }
  1865. + }
  1866. + return len;
  1867. + }
  1868. + return 0;
  1869. +}
  1870. +
  1871. +static int
  1872. scan_ipv4(const char *s, ovs_be32 *key, ovs_be32 *mask)
  1873. {
  1874. int n;
  1875. @@ -4123,6 +4334,23 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
  1876. SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr);
  1877. } SCAN_END_NESTED();
  1878. + SCAN_BEGIN("nsh(", struct ovs_key_nsh) {
  1879. + SCAN_FIELD("nsh_mdtype=", u8, nsh_mdtype);
  1880. + SCAN_FIELD("nsh_np=", u8, nsh_np);
  1881. + SCAN_FIELD("nsp=", nsp, nsp);
  1882. + SCAN_FIELD("nsi=", u8, nsi);
  1883. + SCAN_FIELD("nshc1=", u32, nshc1);
  1884. + SCAN_FIELD("nshc2=", u32, nshc2);
  1885. + SCAN_FIELD("nshc3=", u32, nshc3);
  1886. + SCAN_FIELD("nshc4=", u32, nshc4);
  1887. + } SCAN_END(OVS_KEY_ATTR_NSH);
  1888. +
  1889. + SCAN_BEGIN("encap_eth(", struct ovs_key_encap_eth) {
  1890. + SCAN_FIELD("encap_eth_src=", eth, encap_eth_src);
  1891. + SCAN_FIELD("encap_eth_dst=", eth, encap_eth_dst);
  1892. + SCAN_FIELD("encap_eth_type=", encap_eth_type, encap_eth_type);
  1893. + } SCAN_END(OVS_KEY_ATTR_ENCAP_ETH);
  1894. +
  1895. SCAN_SINGLE_PORT("in_port(", uint32_t, OVS_KEY_ATTR_IN_PORT);
  1896. SCAN_BEGIN("eth(", struct ovs_key_ethernet) {
  1897. @@ -4325,11 +4553,35 @@ union ovs_key_tp {
  1898. static void get_tp_key(const struct flow *, union ovs_key_tp *);
  1899. static void put_tp_key(const union ovs_key_tp *, struct flow *);
  1900. +void
  1901. +get_nsh_key(const struct flow *flow, struct ovs_key_nsh *nsh)
  1902. +{
  1903. + nsh->nsi = flow->nsi;
  1904. + nsh->nsp = flow->nsp;
  1905. + nsh->nsh_mdtype = flow->nsh_mdtype;
  1906. + nsh->nsh_np = flow->nsh_np;
  1907. + nsh->reserved = 0;
  1908. + nsh->nshc1 = flow->nshc1;
  1909. + nsh->nshc2 = flow->nshc2;
  1910. + nsh->nshc3 = flow->nshc3;
  1911. + nsh->nshc4 = flow->nshc4;
  1912. +}
  1913. +
  1914. +void
  1915. +get_encap_eth_key(const struct flow *flow, struct ovs_key_encap_eth *encap_eth)
  1916. +{
  1917. + encap_eth->encap_eth_type = flow->encap_eth_type;
  1918. + encap_eth->encap_eth_src = flow->encap_eth_src;
  1919. + encap_eth->encap_eth_dst = flow->encap_eth_dst;
  1920. +}
  1921. +
  1922. static void
  1923. odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
  1924. bool export_mask, struct ofpbuf *buf)
  1925. {
  1926. struct ovs_key_ethernet *eth_key;
  1927. + struct ovs_key_nsh *nsh_key;
  1928. + struct ovs_key_encap_eth *encap_eth_key;
  1929. size_t encap;
  1930. const struct flow *flow = parms->flow;
  1931. const struct flow *data = export_mask ? parms->mask : parms->flow;
  1932. @@ -4368,6 +4620,18 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
  1933. nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, parms->odp_in_port);
  1934. }
  1935. + if (flow->nsh_mdtype) {
  1936. + nsh_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_NSH,
  1937. + sizeof *nsh_key);
  1938. + get_nsh_key(data, nsh_key);
  1939. + }
  1940. +
  1941. + if (flow->encap_eth_type) {
  1942. + encap_eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ENCAP_ETH,
  1943. + sizeof *encap_eth_key);
  1944. + get_encap_eth_key(data, encap_eth_key);
  1945. + }
  1946. +
  1947. eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ETHERNET,
  1948. sizeof *eth_key);
  1949. get_ethernet_key(data, eth_key);
  1950. @@ -5225,6 +5489,28 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
  1951. flow->in_port.odp_port = ODPP_NONE;
  1952. }
  1953. + /* NSH header. */
  1954. + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_NSH)) {
  1955. + const struct ovs_key_nsh *nsh_key;
  1956. +
  1957. + nsh_key = nl_attr_get(attrs[OVS_KEY_ATTR_NSH]);
  1958. + put_nsh_key(nsh_key, flow);
  1959. + if (is_mask) {
  1960. + expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_NSH;
  1961. + }
  1962. + }
  1963. +
  1964. + /* ENCAP Eth header. */
  1965. + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP_ETH)) {
  1966. + const struct ovs_key_encap_eth *encap_eth_key;
  1967. +
  1968. + encap_eth_key = nl_attr_get(attrs[OVS_KEY_ATTR_ENCAP_ETH]);
  1969. + put_encap_eth_key(encap_eth_key, flow);
  1970. + if (is_mask) {
  1971. + expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ENCAP_ETH;
  1972. + }
  1973. + }
  1974. +
  1975. /* Ethernet header. */
  1976. if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ETHERNET)) {
  1977. const struct ovs_key_ethernet *eth_key;
  1978. @@ -5526,6 +5812,41 @@ put_ethernet_key(const struct ovs_key_ethernet *eth, struct flow *flow)
  1979. flow->dl_dst = eth->eth_dst;
  1980. }
  1981. +void
  1982. +put_nsh_key(const struct ovs_key_nsh *nsh, struct flow *flow)
  1983. +{
  1984. + flow->nsh_mdtype = nsh->nsh_mdtype;
  1985. + flow->nsh_np = nsh->nsh_np;
  1986. + flow->nsi = nsh->nsi;
  1987. + flow->nsp = nsh->nsp;
  1988. + flow->nshc1 = nsh->nshc1;
  1989. + flow->nshc2 = nsh->nshc2;
  1990. + flow->nshc3 = nsh->nshc3;
  1991. + flow->nshc4 = nsh->nshc4;
  1992. +}
  1993. +
  1994. +void
  1995. +flow_zero_nsh(struct flow *flow)
  1996. +{
  1997. + void *dst_p = &(flow->nshc1);
  1998. + memset(dst_p, 0, 24);
  1999. +}
  2000. +
  2001. +void
  2002. +flow_zero_encap_eth(struct flow *flow)
  2003. +{
  2004. + void *dst_p = &flow->encap_eth_src;
  2005. + memset(dst_p, 0, 16);
  2006. +}
  2007. +
  2008. +void
  2009. +put_encap_eth_key(const struct ovs_key_encap_eth *encap_eth, struct flow *flow)
  2010. +{
  2011. + flow->encap_eth_type = encap_eth->encap_eth_type;
  2012. + flow->encap_eth_src = encap_eth->encap_eth_src;
  2013. + flow->encap_eth_dst = encap_eth->encap_eth_dst;
  2014. +}
  2015. +
  2016. static void
  2017. commit_set_ether_addr_action(const struct flow *flow, struct flow *base_flow,
  2018. struct ofpbuf *odp_actions,
  2019. @@ -5577,6 +5898,94 @@ commit_vlan_action(ovs_be16 vlan_tci, struct flow *base,
  2020. base->vlan_tci = vlan_tci;
  2021. }
  2022. +static void
  2023. +commit_nsh_pop_action(const struct flow *flow, struct flow *base,
  2024. + struct ofpbuf *odp_actions, struct flow_wildcards *wc)
  2025. +{
  2026. + struct ovs_key_nsh flow_key, base_key;
  2027. + get_nsh_key(flow, &flow_key);
  2028. + get_nsh_key(base, &base_key);
  2029. +
  2030. + if (memcmp(&flow_key, &base_key, sizeof flow_key)) {
  2031. + memset(&wc->masks.nsh_mdtype, 0xff, sizeof wc->masks.nsh_mdtype);
  2032. +
  2033. + if (base->nsh_mdtype) {
  2034. + nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_NSH);
  2035. + }
  2036. + }
  2037. +}
  2038. +
  2039. +static void
  2040. +commit_nsh_push_action(const struct flow *flow, struct flow *base,
  2041. + struct ofpbuf *odp_actions)
  2042. +{
  2043. + struct ovs_key_nsh flow_key, base_key;
  2044. + get_nsh_key(flow, &flow_key);
  2045. + get_nsh_key(base, &base_key);
  2046. +
  2047. + if (memcmp(&flow_key, &base_key, sizeof flow_key)) {
  2048. + if (flow->nsh_mdtype) {
  2049. + struct ovs_action_push_nsh nsh;
  2050. + nsh.nsh_mdtype = flow->nsh_mdtype;
  2051. + struct nsh_hdr *nsh_hdr = (struct nsh_hdr *)nsh.header;
  2052. + memset(nsh_hdr, 0, sizeof *nsh_hdr);
  2053. + nsh_hdr->base.length = 6;
  2054. + nsh_hdr->base.proto = flow->nsh_np;
  2055. + nsh_hdr->base.mdtype = flow->nsh_mdtype;
  2056. + nsh_hdr->base.proto = flow->nsh_np;
  2057. + nsh_hdr->base.path_hdr = flow->nsp >> 8 | flow->nsi << 24;
  2058. + nsh_hdr->ctx.nshc1 = flow->nshc1;
  2059. + nsh_hdr->ctx.nshc2 = flow->nshc2;
  2060. + nsh_hdr->ctx.nshc3 = flow->nshc3;
  2061. + nsh_hdr->ctx.nshc4 = flow->nshc4;
  2062. + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_NSH,
  2063. + &nsh, sizeof nsh);
  2064. + }
  2065. + }
  2066. +}
  2067. +
  2068. +static void
  2069. +commit_encap_eth_pop_action(const struct flow *flow, struct flow *base,
  2070. + struct ofpbuf *odp_actions, struct flow_wildcards *wc)
  2071. +{
  2072. + struct ovs_key_encap_eth flow_key, base_key;
  2073. + get_encap_eth_key(flow, &flow_key);
  2074. + get_encap_eth_key(base, &base_key);
  2075. +
  2076. + if (memcmp(&flow_key, &base_key, sizeof flow_key)) {
  2077. + memset(&wc->masks.encap_eth_type, 0xff, sizeof wc->masks.encap_eth_type);
  2078. +
  2079. + if (base->encap_eth_type) {
  2080. + nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_ETH);
  2081. + }
  2082. + }
  2083. +}
  2084. +
  2085. +static void
  2086. +commit_encap_eth_push_action(const struct flow *flow, struct flow *base,
  2087. + struct ofpbuf *odp_actions)
  2088. +{
  2089. + struct ovs_key_encap_eth flow_key, base_key;
  2090. + get_encap_eth_key(flow, &flow_key);
  2091. + get_encap_eth_key(base, &base_key);
  2092. +
  2093. + if (memcmp(&flow_key, &base_key, sizeof flow_key)) {
  2094. + if (flow->encap_eth_type) {
  2095. + struct ovs_action_push_eth encap_eth;
  2096. + encap_eth.encap_eth_type = flow->encap_eth_type;
  2097. + struct encap_eth_hdr *encap_eth_header =
  2098. + (struct encap_eth_hdr *)encap_eth.header;
  2099. + void *dst_p = encap_eth_header->encap_eth_dst.ea;
  2100. + void *src_p = encap_eth_header->encap_eth_src.ea;
  2101. + memcpy(dst_p, flow->encap_eth_dst.ea, sizeof flow->encap_eth_dst);
  2102. + memcpy(src_p, flow->encap_eth_src.ea, sizeof flow->encap_eth_src);
  2103. + encap_eth_header->encap_eth_type = htons(ETH_P_NSH);
  2104. + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_ETH,
  2105. + &encap_eth, sizeof encap_eth);
  2106. + }
  2107. + }
  2108. +}
  2109. +
  2110. /* Wildcarding already done at action translation time. */
  2111. static void
  2112. commit_mpls_action(const struct flow *flow, struct flow *base,
  2113. @@ -6008,6 +6417,10 @@ commit_odp_actions(const struct flow *flow, struct flow *base,
  2114. slow2 = commit_set_icmp_action(flow, base, odp_actions, wc);
  2115. commit_mpls_action(flow, base, odp_actions);
  2116. commit_vlan_action(flow->vlan_tci, base, odp_actions, wc);
  2117. + commit_encap_eth_pop_action(flow, base, odp_actions, wc);
  2118. + commit_nsh_pop_action(flow, base, odp_actions, wc);
  2119. + commit_nsh_push_action(flow, base, odp_actions);
  2120. + commit_encap_eth_push_action(flow, base, odp_actions);
  2121. commit_set_priority_action(flow, base, odp_actions, wc, use_masked);
  2122. commit_set_pkt_mark_action(flow, base, odp_actions, wc, use_masked);
  2123. diff --git a/lib/odp-util.h b/lib/odp-util.h
  2124. index 51cf5c3..2cb04f1 100644
  2125. --- a/lib/odp-util.h
  2126. +++ b/lib/odp-util.h
  2127. @@ -66,7 +66,7 @@ enum slow_path_reason {
  2128. /* Mask of all slow_path_reasons. */
  2129. enum {
  2130. SLOW_PATH_REASON_MASK = 0
  2131. -#define SPR(ENUM, STRING, EXPLANATION) | 1 << ENUM##_INDEX
  2132. +#define SPR(ENUM, STRING, EXPLANATION) | 1 << ENUM##_INDEX
  2133. SLOW_PATH_REASONS
  2134. #undef SPR
  2135. };
  2136. @@ -126,6 +126,8 @@ void odp_portno_names_destroy(struct hmap *portno_names);
  2137. * OVS_KEY_ATTR_CT_ZONE 2 2 4 8
  2138. * OVS_KEY_ATTR_CT_MARK 4 -- 4 8
  2139. * OVS_KEY_ATTR_CT_LABEL 16 -- 4 20
  2140. + * OVS_KEY_ATTR_NSH 24 -- 4 28
  2141. + * OVS_KEY_ATTR_ENCAP 14 -- 4 18
  2142. * OVS_KEY_ATTR_ETHERNET 12 -- 4 16
  2143. * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype)
  2144. * OVS_KEY_ATTR_VLAN 2 2 4 8
  2145. @@ -150,6 +152,12 @@ struct odputil_keybuf {
  2146. uint32_t keybuf[DIV_ROUND_UP(ODPUTIL_FLOW_KEY_BYTES, 4)];
  2147. };
  2148. +void put_nsh_key(const struct ovs_key_nsh *, struct flow *);
  2149. +void get_nsh_key(const struct flow *flow, struct ovs_key_nsh *nsh);
  2150. +void put_encap_eth_key(const struct ovs_key_encap_eth *encap_eth, struct flow *flow);
  2151. +void get_encap_eth_key(const struct flow *flow, struct ovs_key_encap_eth *encap_eth);
  2152. +void flow_zero_nsh(struct flow *);
  2153. +void flow_zero_encap_eth(struct flow *);
  2154. enum odp_key_fitness odp_tun_key_from_attr(const struct nlattr *, bool udpif,
  2155. struct flow_tnl *);
  2156. diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
  2157. index aac4ff0..f4062b2 100644
  2158. --- a/lib/ofp-actions.c
  2159. +++ b/lib/ofp-actions.c
  2160. @@ -299,6 +299,18 @@ enum ofp_raw_action_type {
  2161. /* NX1.0+(36): struct nx_action_nat, ... */
  2162. NXAST_RAW_NAT,
  2163. + /* NX1.0+(38): void. */
  2164. + NXAST_RAW_PUSH_NSH,
  2165. +
  2166. + /* NX1.0+(39): void. */
  2167. + NXAST_RAW_POP_NSH,
  2168. +
  2169. + /* NX1.0+(40): void. */
  2170. + NXAST_RAW_PUSH_ETH,
  2171. +
  2172. + /* NX1.0+(41): void. */
  2173. + NXAST_RAW_POP_ETH,
  2174. +
  2175. /* ## ------------------ ## */
  2176. /* ## Debugging actions. ## */
  2177. /* ## ------------------ ## */
  2178. @@ -1624,7 +1636,127 @@ format_PUSH_VLAN(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2179. ds_put_format(s, "%spush_vlan:%s%#"PRIx16,
  2180. colors.param, colors.end, ETH_TYPE_VLAN_8021Q);
  2181. }
  2182. -
  2183. +
  2184. +/* Push NSH header actions. */
  2185. +static enum ofperr
  2186. +decode_NXAST_RAW_PUSH_NSH(struct ofpbuf * out)
  2187. +{
  2188. + ofpact_put_PUSH_NSH(out)->ofpact.raw = NXAST_RAW_PUSH_NSH;
  2189. +
  2190. + return 0;
  2191. +}
  2192. +
  2193. +static void
  2194. +encode_PUSH_NSH(const struct ofpact_null *null OVS_UNUSED,
  2195. + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
  2196. +{
  2197. + put_NXAST_PUSH_NSH(out);
  2198. +}
  2199. +
  2200. +static char * OVS_WARN_UNUSED_RESULT
  2201. +parse_PUSH_NSH(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
  2202. + enum ofputil_protocol *usable_protocols OVS_UNUSED)
  2203. +{
  2204. + ofpact_put_PUSH_NSH(ofpacts)->ofpact.raw = NXAST_RAW_PUSH_NSH;;
  2205. + return NULL;
  2206. +}
  2207. +
  2208. +static void
  2209. +format_PUSH_NSH(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2210. +{
  2211. + ds_put_format(s, "push_nsh");
  2212. +}
  2213. +
  2214. +/* Pop NSH header actions. */
  2215. +static enum ofperr
  2216. +decode_NXAST_RAW_POP_NSH(struct ofpbuf * out)
  2217. +{
  2218. + ofpact_put_POP_NSH(out)->ofpact.raw = NXAST_RAW_POP_NSH;
  2219. +
  2220. + return 0;
  2221. +}
  2222. +
  2223. +static void
  2224. +encode_POP_NSH(const struct ofpact_null *null OVS_UNUSED,
  2225. + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
  2226. +{
  2227. + put_NXAST_POP_NSH(out);
  2228. +}
  2229. +
  2230. +static char * OVS_WARN_UNUSED_RESULT
  2231. +parse_POP_NSH(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
  2232. + enum ofputil_protocol *usable_protocols OVS_UNUSED)
  2233. +{
  2234. + ofpact_put_POP_NSH(ofpacts)->ofpact.raw = NXAST_RAW_POP_NSH;
  2235. + return NULL;
  2236. +}
  2237. +
  2238. +static void
  2239. +format_POP_NSH(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2240. +{
  2241. + ds_put_format(s, "pop_nsh");
  2242. +}
  2243. +
  2244. +/* Push ENCAP Eth header actions. */
  2245. +static enum ofperr
  2246. +decode_NXAST_RAW_PUSH_ETH(struct ofpbuf * out)
  2247. +{
  2248. + ofpact_put_PUSH_ETH(out)->ofpact.raw = NXAST_RAW_PUSH_ETH;
  2249. +
  2250. + return 0;
  2251. +}
  2252. +
  2253. +static void
  2254. +encode_PUSH_ETH(const struct ofpact_null *null OVS_UNUSED,
  2255. + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
  2256. +{
  2257. + put_NXAST_PUSH_ETH(out);
  2258. +}
  2259. +
  2260. +static char * OVS_WARN_UNUSED_RESULT
  2261. +parse_PUSH_ETH(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
  2262. + enum ofputil_protocol *usable_protocols OVS_UNUSED)
  2263. +{
  2264. + ofpact_put_PUSH_ETH(ofpacts)->ofpact.raw = NXAST_RAW_PUSH_ETH;;
  2265. + return NULL;
  2266. +}
  2267. +
  2268. +static void
  2269. +format_PUSH_ETH(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2270. +{
  2271. + ds_put_format(s, "push_eth");
  2272. +}
  2273. +
  2274. +/* Pop ENCAP ETH header actions. */
  2275. +static enum ofperr
  2276. +decode_NXAST_RAW_POP_ETH(struct ofpbuf * out)
  2277. +{
  2278. + ofpact_put_POP_ETH(out)->ofpact.raw = NXAST_RAW_POP_ETH;
  2279. +
  2280. + return 0;
  2281. +}
  2282. +
  2283. +static void
  2284. +encode_POP_ETH(const struct ofpact_null *null OVS_UNUSED,
  2285. + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
  2286. +{
  2287. + put_NXAST_POP_ETH(out);
  2288. +}
  2289. +
  2290. +static char * OVS_WARN_UNUSED_RESULT
  2291. +parse_POP_ETH(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
  2292. + enum ofputil_protocol *usable_protocols OVS_UNUSED)
  2293. +{
  2294. + ofpact_put_POP_ETH(ofpacts)->ofpact.raw = NXAST_RAW_POP_ETH;
  2295. + return NULL;
  2296. +}
  2297. +
  2298. +static void
  2299. +format_POP_ETH(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2300. +{
  2301. + ds_put_format(s, "pop_eth");
  2302. +}
  2303. +
  2304. /* Action structure for OFPAT10_SET_DL_SRC/DST and OFPAT11_SET_DL_SRC/DST. */
  2305. struct ofp_action_dl_addr {
  2306. ovs_be16 type; /* Type. */
  2307. @@ -5910,6 +6042,10 @@ ofpact_is_set_or_move_action(const struct ofpact *a)
  2308. case OFPACT_POP_QUEUE:
  2309. case OFPACT_PUSH_MPLS:
  2310. case OFPACT_PUSH_VLAN:
  2311. + case OFPACT_PUSH_NSH:
  2312. + case OFPACT_POP_NSH:
  2313. + case OFPACT_PUSH_ETH:
  2314. + case OFPACT_POP_ETH:
  2315. case OFPACT_RESUBMIT:
  2316. case OFPACT_SAMPLE:
  2317. case OFPACT_STACK_POP:
  2318. @@ -5937,6 +6073,10 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
  2319. case OFPACT_POP_MPLS:
  2320. case OFPACT_PUSH_MPLS:
  2321. case OFPACT_PUSH_VLAN:
  2322. + case OFPACT_PUSH_NSH:
  2323. + case OFPACT_POP_NSH:
  2324. + case OFPACT_PUSH_ETH:
  2325. + case OFPACT_POP_ETH:
  2326. case OFPACT_REG_MOVE:
  2327. case OFPACT_SET_FIELD:
  2328. case OFPACT_SET_ETH_DST:
  2329. @@ -6162,6 +6302,10 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
  2330. case OFPACT_SET_VLAN_PCP:
  2331. case OFPACT_STRIP_VLAN:
  2332. case OFPACT_PUSH_VLAN:
  2333. + case OFPACT_PUSH_NSH:
  2334. + case OFPACT_POP_NSH:
  2335. + case OFPACT_PUSH_ETH:
  2336. + case OFPACT_POP_ETH:
  2337. case OFPACT_SET_ETH_SRC:
  2338. case OFPACT_SET_ETH_DST:
  2339. case OFPACT_SET_IPV4_SRC:
  2340. @@ -6709,6 +6853,10 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,
  2341. case OFPACT_SET_TUNNEL:
  2342. case OFPACT_SET_QUEUE:
  2343. case OFPACT_POP_QUEUE:
  2344. + case OFPACT_PUSH_NSH:
  2345. + case OFPACT_POP_NSH:
  2346. + case OFPACT_PUSH_ETH:
  2347. + case OFPACT_POP_ETH:
  2348. case OFPACT_RESUBMIT:
  2349. return 0;
  2350. @@ -7266,6 +7414,10 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
  2351. case OFPACT_SET_VLAN_PCP:
  2352. case OFPACT_STRIP_VLAN:
  2353. case OFPACT_PUSH_VLAN:
  2354. + case OFPACT_PUSH_NSH:
  2355. + case OFPACT_POP_NSH:
  2356. + case OFPACT_PUSH_ETH:
  2357. + case OFPACT_POP_ETH:
  2358. case OFPACT_SET_ETH_SRC:
  2359. case OFPACT_SET_ETH_DST:
  2360. case OFPACT_SET_IPV4_SRC:
  2361. diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
  2362. index 4bd8854..3897c0b 100644
  2363. --- a/lib/ofp-actions.h
  2364. +++ b/lib/ofp-actions.h
  2365. @@ -93,6 +93,12 @@
  2366. OFPACT(POP_QUEUE, ofpact_null, ofpact, "pop_queue") \
  2367. OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact, "fin_timeout") \
  2368. \
  2369. + /* NSH */ \
  2370. + OFPACT(PUSH_NSH, ofpact_null, ofpact, "push_nsh") \
  2371. + OFPACT(POP_NSH, ofpact_null, ofpact, "pop_nsh") \
  2372. + OFPACT(PUSH_ETH, ofpact_null, ofpact, "push_eth") \
  2373. + OFPACT(POP_ETH, ofpact_null, ofpact, "pop_eth") \
  2374. + \
  2375. /* Flow table interaction. */ \
  2376. OFPACT(RESUBMIT, ofpact_resubmit, ofpact, "resubmit") \
  2377. OFPACT(LEARN, ofpact_learn, specs, "learn") \
  2378. diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
  2379. index fbc82b7..e15e8d2 100644
  2380. --- a/ofproto/ofproto-dpif-sflow.c
  2381. +++ b/ofproto/ofproto-dpif-sflow.c
  2382. @@ -976,6 +976,8 @@ sflow_read_set_action(const struct nlattr *attr,
  2383. case OVS_KEY_ATTR_IN_PORT:
  2384. case OVS_KEY_ATTR_ETHERNET:
  2385. case OVS_KEY_ATTR_VLAN:
  2386. + case OVS_KEY_ATTR_NSH:
  2387. + case OVS_KEY_ATTR_ENCAP_ETH:
  2388. break;
  2389. case OVS_KEY_ATTR_MPLS: {
  2390. diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
  2391. index 2612b7d..f59eed8 100644
  2392. --- a/ofproto/ofproto-dpif-upcall.c
  2393. +++ b/ofproto/ofproto-dpif-upcall.c
  2394. @@ -39,6 +39,7 @@
  2395. #include "seq.h"
  2396. #include "unixctl.h"
  2397. #include "openvswitch/vlog.h"
  2398. +#include "odp-util.h"
  2399. #define MAX_QUEUE_LENGTH 512
  2400. #define UPCALL_MAX_BATCH 64
  2401. @@ -746,6 +747,9 @@ recv_upcalls(struct handler *handler)
  2402. struct upcall *upcall = &upcalls[n_upcalls];
  2403. struct flow *flow = &flows[n_upcalls];
  2404. unsigned int mru;
  2405. + struct ovs_key_nsh reserve_nsh;
  2406. + struct ovs_key_encap_eth reserve_encap_eth;
  2407. + bool nsh_mdtype_flag, encap_eth_type_flag;
  2408. int error;
  2409. ofpbuf_use_stub(recv_buf, recv_stubs[n_upcalls],
  2410. @@ -796,8 +800,23 @@ recv_upcalls(struct handler *handler)
  2411. }
  2412. pkt_metadata_from_flow(&dupcall->packet.md, flow);
  2413. +
  2414. + nsh_mdtype_flag = !!(flow->nsh_mdtype);
  2415. + encap_eth_type_flag = !!(flow->encap_eth_type);
  2416. + if(nsh_mdtype_flag)
  2417. + get_nsh_key(flow, &reserve_nsh);
  2418. +
  2419. + if(encap_eth_type_flag)
  2420. + get_encap_eth_key(flow, &reserve_encap_eth);
  2421. +
  2422. flow_extract(&dupcall->packet, flow);
  2423. + if(nsh_mdtype_flag)
  2424. + put_nsh_key(&reserve_nsh, flow);
  2425. +
  2426. + if(encap_eth_type_flag)
  2427. + put_encap_eth_key(&reserve_encap_eth, flow);
  2428. +
  2429. error = process_upcall(udpif, upcall,
  2430. &upcall->odp_actions, &upcall->wc);
  2431. if (error) {
  2432. diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
  2433. index a02dc24..4f91d0a 100644
  2434. --- a/ofproto/ofproto-dpif-xlate.c
  2435. +++ b/ofproto/ofproto-dpif-xlate.c
  2436. @@ -4240,6 +4240,10 @@ freeze_unroll_actions(const struct ofpact *a, const struct ofpact *end,
  2437. case OFPACT_SET_VLAN_PCP:
  2438. case OFPACT_STRIP_VLAN:
  2439. case OFPACT_PUSH_VLAN:
  2440. + case OFPACT_PUSH_NSH:
  2441. + case OFPACT_POP_NSH:
  2442. + case OFPACT_PUSH_ETH:
  2443. + case OFPACT_POP_ETH:
  2444. case OFPACT_SET_ETH_SRC:
  2445. case OFPACT_SET_ETH_DST:
  2446. case OFPACT_SET_IPV4_SRC:
  2447. @@ -4524,6 +4528,24 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
  2448. }
  2449. break;
  2450. + case OFPACT_PUSH_NSH:
  2451. + memset(&wc->masks.nsh_mdtype, 0xff, sizeof wc->masks.nsh_mdtype);
  2452. + break;
  2453. +
  2454. + case OFPACT_POP_NSH:
  2455. + memset(&wc->masks.nsh_mdtype, 0xff, sizeof wc->masks.nsh_mdtype);
  2456. + flow_zero_nsh(flow);
  2457. + break;
  2458. +
  2459. + case OFPACT_PUSH_ETH:
  2460. + memset(&wc->masks.encap_eth_type, 0xff, sizeof wc->masks.encap_eth_type);
  2461. + break;
  2462. +
  2463. + case OFPACT_POP_ETH:
  2464. + memset(&wc->masks.encap_eth_type, 0xff, sizeof wc->masks.encap_eth_type);
  2465. + flow_zero_encap_eth(flow);
  2466. + break;
  2467. +
  2468. case OFPACT_STRIP_VLAN:
  2469. memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
  2470. flow->vlan_tci = htons(0);
  2471. diff --git a/tests/ofproto.at b/tests/ofproto.at
  2472. index 6c7217d..7141e39 100644
  2473. --- a/tests/ofproto.at
  2474. +++ b/tests/ofproto.at
  2475. @@ -1777,7 +1777,7 @@ head_table () {
  2476. actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue
  2477. supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_gpe_np tun_gpe_flags tun_metadata0 dnl
  2478. tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 dnl
  2479. -metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll
  2480. +metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nsp nsi nshc1 nshc2 nshc3 nshc4 nsh_mdtype nsh_np encap_eth_src encap_eth_dst encap_eth_type
  2481. matching:
  2482. dp_hash: arbitrary mask
  2483. recirc_id: exact match or wildcard
  2484. @@ -1917,6 +1917,17 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4
  2485. nd_target: arbitrary mask
  2486. nd_sll: arbitrary mask
  2487. nd_tll: arbitrary mask
  2488. + nsp: arbitrary mask
  2489. + nsi: arbitrary mask
  2490. + nshc1: arbitrary mask
  2491. + nshc2: arbitrary mask
  2492. + nshc3: arbitrary mask
  2493. + nshc4: arbitrary mask
  2494. + nsh_mdtype: arbitrary mask
  2495. + nsh_np: arbitrary mask
  2496. + encap_eth_src: arbitrary mask
  2497. + encap_eth_dst: arbitrary mask
  2498. + encap_eth_type: exact match or wildcard
  2499. ' $1
  2500. }
  2501. diff --git a/tests/tunnel.at b/tests/tunnel.at
  2502. index 0c033da..d957574 100644
  2503. --- a/tests/tunnel.at
  2504. +++ b/tests/tunnel.at
  2505. @@ -412,6 +412,163 @@ AT_CHECK([tail -1 stdout], [0],
  2506. OVS_VSWITCHD_STOP
  2507. AT_CLEANUP
  2508. +AT_SETUP([tunnel - VXLAN-GPE and NSH - Encapsulation - kernel space])
  2509. +OVS_VSWITCHD_START([dnl
  2510. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2511. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2512. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2513. + options:exts=gpe])
  2514. +
  2515. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2516. +ADD_OF_PORTS([br0], [90])
  2517. +AT_DATA([flows.txt], [dnl
  2518. +in_port=90 actions=resubmit:1,resubmit:2
  2519. +in_port=1 actions=push_nsh,set_field:1->nsh_mdtype,set_field:0x3->nsh_np,set_field:0x112233->nsp,set_field:0x44->nsi,set_field:0x11223344->nshc1,set_field:0x55667788->nshc2,set_field:0x99aabbcc->nshc3,set_field:0xddeeff00->nshc4,output:1
  2520. +in_port=2 actions=push_nsh,set_field:1->nsh_mdtype,set_field:0x3->nsh_np,set_field:0x112233->nsp,set_field:0x44->nsi,set_field:0x11223344->nshc1,set_field:0x55667788->nshc2,set_field:0x99aabbcc->nshc3,set_field:0xddeeff00->nshc4,set_field:4->tun_gpe_np,output:2
  2521. +])
  2522. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2523. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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])
  2524. +AT_CHECK([tail -1 stdout], [0],
  2525. + [Datapath actions: push_nsh(nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=287454020,nshc2=1432778632,nshc3=2578103244,nshc4=3723427584),1,set(tunnel(tun_id=0x0,dst=1.1.1.1,ttl=64,vxlan(gpe(np=0x4,flags=0)),flags(df|key))),push_nsh(nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=287454020,nshc2=1432778632,nshc3=2578103244,nshc4=3723427584),4790
  2526. +])
  2527. +
  2528. +OVS_VSWITCHD_STOP
  2529. +AT_CLEANUP
  2530. +
  2531. +AT_SETUP([tunnel - VXLAN-GPE and NSH - Decapsulation - kernel space])
  2532. +OVS_VSWITCHD_START([dnl
  2533. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2534. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2535. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2536. + options:exts=gpe])
  2537. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2538. +
  2539. +AT_DATA([flows.txt], [dnl
  2540. +priority=200,in_port=2,tun_gpe_np=4,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,actions=pop_nsh,output=1
  2541. +])
  2542. +
  2543. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2544. +
  2545. +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
  2546. + br0 65534/100: (dummy)
  2547. + p1 1/1: (dummy)
  2548. + p2 2/4790: (vxlan: dst_port=4790, key=flow, remote_ip=1.1.1.1)
  2549. +])
  2550. +
  2551. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(src=1.1.1.1,dst=1.2.3.4,ttl=64,flags(),vxlan(gpe(np=4,flags=0x0c))),in_port(4790),nsh(nsh_mdtype=1,nsh_np=3,nsp=0x112233,nsi=0x44,nshc1=0x11223344,nshc2=0x55667788,nshc3=0x99aabbcc,nshc4=0xddeeff00),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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
  2552. +AT_CHECK([tail -1 stdout], [0],
  2553. + [Datapath actions: pop_nsh,1
  2554. +])
  2555. +
  2556. +OVS_VSWITCHD_STOP
  2557. +AT_CLEANUP
  2558. +
  2559. +AT_SETUP([Eth and NSH - Encapsulation - kernel space])
  2560. +OVS_VSWITCHD_START([dnl
  2561. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2562. + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
  2563. +
  2564. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2565. +ADD_OF_PORTS([br0], [90])
  2566. +AT_DATA([flows.txt], [dnl
  2567. +in_port=90 actions=resubmit:1,resubmit:2
  2568. +in_port=1 actions=push_nsh,set_field:1->nsh_mdtype,set_field:0x3->nsh_np,set_field:0x112233->nsp,set_field:0x44->nsi,set_field:0x11223344->nshc1,set_field:0x55667788->nshc2,set_field:0x99aabbcc->nshc3,push_eth,set_field:0x894f->encap_eth_type,set_field:00:11:22:33:44:55->encap_eth_dst,set_field:00:66:77:88:99:aa->encap_eth_src,output:1
  2569. +in_port=2 actions=push_nsh,set_field:1->nsh_mdtype,set_field:0x3->nsh_np,set_field:0x112233->nsp,set_field:0x44->nsi,set_field:0x11223344->nshc1,set_field:0x55667788->nshc2,set_field:0x99aabbcc->nshc3,set_field:0xddeeff00->nshc4,output:2
  2570. +])
  2571. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2572. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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])
  2573. +AT_CHECK([tail -1 stdout], [0],
  2574. +[Datapath actions: push_nsh(nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=287454020,nshc2=1432778632,nshc3=2578103244,nshc4=0),push_eth(encap_eth_type=35151,encap_eth_src=00:66:77:88:99:aa,encap_eth_dst=00:11:22:33:44:55,),1,push_nsh(nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=287454020,nshc2=1432778632,nshc3=2578103244,nshc4=3723427584),push_eth(encap_eth_type=35151,encap_eth_src=00:66:77:88:99:aa,encap_eth_dst=00:11:22:33:44:55,),2
  2575. +])
  2576. +
  2577. +OVS_VSWITCHD_STOP
  2578. +AT_CLEANUP
  2579. +
  2580. +AT_SETUP([Eth and NSH - Decapsulation - kernel space])
  2581. +OVS_VSWITCHD_START([dnl
  2582. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2583. + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
  2584. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2585. +
  2586. +AT_DATA([flows.txt], [dnl
  2587. +priority=200,in_port=2,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,encap_eth_type=0x894f,encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa,actions=pop_nsh,pop_eth,output=1
  2588. +])
  2589. +
  2590. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2591. +
  2592. +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
  2593. + br0 65534/100: (dummy)
  2594. + p1 1/1: (dummy)
  2595. + p2 2/2: (dummy)
  2596. +])
  2597. +
  2598. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy ',in_port(2),encap_eth(encap_eth_type=0x894f,encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa),nsh(nsh_mdtype=1,nsh_np=3,nsp=0x112233,nsi=0x44,nshc1=0x11223344,nshc2=0x55667788,nshc3=0x99aabbcc,nshc4=0xddeeff00),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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
  2599. +AT_CHECK([tail -1 stdout], [0],
  2600. + [Datapath actions: pop_eth,pop_nsh,1
  2601. +])
  2602. +
  2603. +OVS_VSWITCHD_STOP
  2604. +AT_CLEANUP
  2605. +
  2606. +AT_SETUP([VXLANGPE+NSH to Eth+NSH - kernel space])
  2607. +OVS_VSWITCHD_START([dnl
  2608. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2609. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2610. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2611. + options:exts=gpe])
  2612. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2613. +
  2614. +AT_DATA([flows.txt], [dnl
  2615. +priority=200,in_port=2,tun_gpe_np=4,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,actions=push_eth,set_field:0x894f->encap_eth_type,set_field:00:11:22:33:44:55->encap_eth_dst,set_field:00:66:77:88:99:aa->encap_eth_src,output:1
  2616. +
  2617. +])
  2618. +
  2619. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2620. +
  2621. +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
  2622. + br0 65534/100: (dummy)
  2623. + p1 1/1: (dummy)
  2624. + p2 2/4790: (vxlan: dst_port=4790, key=flow, remote_ip=1.1.1.1)
  2625. +])
  2626. +
  2627. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(src=1.1.1.1,dst=1.2.3.4,ttl=64,flags(),vxlan(gpe(np=4,flags=0x0c))),in_port(4790),nsh(nsh_mdtype=1,nsh_np=3,nsp=0x112233,nsi=0x44,nshc1=0x11223344,nshc2=0x55667788,nshc3=0x99aabbcc,nshc4=0xddeeff00),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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
  2628. +AT_CHECK([tail -1 stdout], [0],
  2629. + [Datapath actions: push_eth(encap_eth_type=35151,encap_eth_src=00:66:77:88:99:aa,encap_eth_dst=00:11:22:33:44:55,),1
  2630. +])
  2631. +
  2632. +OVS_VSWITCHD_STOP
  2633. +AT_CLEANUP
  2634. +
  2635. +AT_SETUP([Eth+NSH to VXLANGPE+NSH - kernel space])
  2636. +OVS_VSWITCHD_START([dnl
  2637. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2638. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2639. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2640. + options:exts=gpe])
  2641. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2642. +
  2643. +AT_DATA([flows.txt], [dnl
  2644. +priority=200,in_port=1,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,encap_eth_type=0x894f,encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa,actions=pop_eth,set_field:0x4->tun_gpe_np,output=2
  2645. +])
  2646. +
  2647. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2648. +
  2649. +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
  2650. + br0 65534/100: (dummy)
  2651. + p1 1/1: (dummy)
  2652. + p2 2/4790: (vxlan: dst_port=4790, key=flow, remote_ip=1.1.1.1)
  2653. +])
  2654. +
  2655. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy ',in_port(1),encap_eth(encap_eth_type=0x894f,encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa),,nsh(nsh_mdtype=1,nsh_np=3,nsp=0x112233,nsi=0x44,nshc1=0x11223344,nshc2=0x55667788,nshc3=0x99aabbcc,nshc4=0xddeeff00),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=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
  2656. +AT_CHECK([tail -1 stdout], [0],
  2657. + [Datapath actions: set(tunnel(tun_id=0x0,dst=1.1.1.1,ttl=64,vxlan(gpe(np=0x4,flags=0)),flags(df|key))),pop_eth,4790
  2658. +])
  2659. +
  2660. +OVS_VSWITCHD_STOP
  2661. +AT_CLEANUP
  2662. +
  2663. +
  2664. +
  2665. AT_SETUP([tunnel - Geneve metadata])
  2666. OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \
  2667. options:remote_ip=1.1.1.1 ofport_request=1 \
  2668. --
  2669. 1.9.3