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-Add-NSH-support-in-kernel-and-userspace-data-planes.patch 114KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147
  1. From 653c2f6777a6c4f3559a55c8f5a88f4aca313788 Mon Sep 17 00:00:00 2001
  2. From: Yi Yang <yi.y.yang@intel.com>
  3. Date: Mon, 14 Nov 2016 12:08:14 +0800
  4. Subject: [PATCH 2/8] Add NSH support in kernel and userspace data planes
  5. features includes:
  6. * push_nsh and pop_nsh actions
  7. * support Ethernet+NSH and VxLAN-gpe+NSH
  8. * support the same features in DPDK netdev
  9. * news match fields: nsp, nsi, nshc1, nshc2, nshc3, nshc4, nsh_mdtype,
  10. nsh_np, encap_eth_src, encap_eth_dst, encap_eth_type, gpe_np
  11. Signed-off-by: Yi Yang <yi.y.yang@intel.com>
  12. ---
  13. datapath/actions.c | 39 +++
  14. datapath/datapath.h | 2 +
  15. datapath/flow.c | 101 +++++++
  16. datapath/flow.h | 1 +
  17. datapath/flow_netlink.c | 59 +++-
  18. datapath/linux/compat/include/linux/openvswitch.h | 166 ++++++++++++
  19. include/openvswitch/automake.mk | 3 +-
  20. include/openvswitch/flow.h | 19 +-
  21. include/openvswitch/match.h | 24 ++
  22. include/openvswitch/meta-flow.h | 174 ++++++++++++
  23. include/openvswitch/ofp-actions.h | 4 +
  24. include/openvswitch/vxlangpe.h | 76 ++++++
  25. lib/dpif-netdev.c | 39 ++-
  26. lib/dpif.c | 2 +
  27. lib/flow.c | 106 +++++++-
  28. lib/match.c | 189 +++++++++++++
  29. lib/meta-flow.c | 256 +++++++++++++++++-
  30. lib/netdev-native-tnl.c | 91 ++++++-
  31. lib/netdev-vport.c | 10 +-
  32. lib/netdev-vport.h | 6 +
  33. lib/nx-match.c | 18 ++
  34. lib/odp-execute.c | 19 ++
  35. lib/odp-util.c | 279 ++++++++++++++++++-
  36. lib/odp-util.h | 6 +-
  37. lib/ofp-actions.c | 80 +++++-
  38. lib/packets.c | 23 ++
  39. lib/packets.h | 3 +
  40. ofproto/ofproto-dpif-sflow.c | 1 +
  41. ofproto/ofproto-dpif-upcall.c | 11 +
  42. ofproto/ofproto-dpif-xlate.c | 13 +
  43. ofproto/ofproto-dpif.h | 1 -
  44. ofproto/tunnel.c | 1 +
  45. tests/ofproto.at | 12 +-
  46. tests/tunnel.at | 316 ++++++++++++++++++++++
  47. 34 files changed, 2115 insertions(+), 35 deletions(-)
  48. create mode 100644 include/openvswitch/vxlangpe.h
  49. diff --git a/datapath/actions.c b/datapath/actions.c
  50. index 82833d0..c979596 100644
  51. --- a/datapath/actions.c
  52. +++ b/datapath/actions.c
  53. @@ -265,6 +265,37 @@ static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key,
  54. ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
  55. }
  56. +static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
  57. +{
  58. + if (!pskb_may_pull(skb, ETH_NSH_TYPE1_HEADER_SIZE))
  59. + return -ENOMEM;
  60. + else
  61. + __skb_pull(skb, ETH_NSH_TYPE1_HEADER_SIZE);
  62. +
  63. + return 0;
  64. +}
  65. +
  66. +static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key,
  67. + const struct ovs_action_push_nsh *nsh)
  68. +{
  69. +
  70. + if (nsh->nsh_mdtype == NSH_M_TYPE1) {
  71. + if (skb_cow_head(skb, ETH_NSH_TYPE1_HEADER_SIZE) < 0) {
  72. + return -ENOMEM;
  73. + }
  74. +
  75. + skb_push(skb, ETH_NSH_TYPE1_HEADER_SIZE);
  76. + OVS_CB(skb)->encap_eth_header = (struct encap_eth_hdr *)skb->data;
  77. + OVS_CB(skb)->nsh_header = (struct nsh_hdr *)(skb->data + ENCAP_ETH_LEN);
  78. + memcpy(skb->data, nsh->header, ETH_NSH_TYPE1_HEADER_SIZE);
  79. + OVS_CB(skb)->encap_eth_header->encap_eth_type = htons(ETH_P_NSH);
  80. + }
  81. + else
  82. + return -EINVAL;
  83. +
  84. + return 0;
  85. +}
  86. +
  87. /* 'src' is already properly masked. */
  88. static void ether_addr_copy_masked(u8 *dst_, const u8 *src_, const u8 *mask_)
  89. {
  90. @@ -1140,6 +1171,14 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
  91. err = pop_vlan(skb, key);
  92. break;
  93. + case OVS_ACTION_ATTR_PUSH_NSH:
  94. + err = push_nsh(skb, key, nla_data(a));
  95. + break;
  96. +
  97. + case OVS_ACTION_ATTR_POP_NSH:
  98. + err = pop_nsh(skb, key);
  99. + break;
  100. +
  101. case OVS_ACTION_ATTR_RECIRC:
  102. err = execute_recirc(dp, skb, key, a, rem);
  103. if (nla_is_last(a, rem)) {
  104. diff --git a/datapath/datapath.h b/datapath/datapath.h
  105. index 22bbaac..a6b2a44 100644
  106. --- a/datapath/datapath.h
  107. +++ b/datapath/datapath.h
  108. @@ -108,6 +108,8 @@ struct ovs_skb_cb {
  109. struct vport *input_vport;
  110. u16 mru;
  111. u32 cutlen;
  112. + struct nsh_hdr *nsh_header;
  113. + struct encap_eth_hdr *encap_eth_header;
  114. };
  115. #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
  116. diff --git a/datapath/flow.c b/datapath/flow.c
  117. index 390286c..8c4d583 100644
  118. --- a/datapath/flow.c
  119. +++ b/datapath/flow.c
  120. @@ -44,6 +44,7 @@
  121. #include <net/ipv6.h>
  122. #include <net/mpls.h>
  123. #include <net/ndisc.h>
  124. +#include <net/vxlan.h>
  125. #include "datapath.h"
  126. #include "conntrack.h"
  127. @@ -323,6 +324,26 @@ static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
  128. return 0;
  129. }
  130. +static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key){
  131. + struct nsh_hdr *nsh_hdr = NULL;
  132. +
  133. + OVS_CB(skb)->encap_eth_header = (struct encap_eth_hdr *)skb->data;
  134. + nsh_hdr = (struct nsh_hdr *)((const char *)skb->data + ENCAP_ETH_LEN);
  135. + OVS_CB(skb)->nsh_header = nsh_hdr;
  136. + memcpy(&key->nsh.encap_eth_dst, skb->data, ENCAP_ETH_LEN);
  137. + key->nsh.nsh_mdtype = nsh_hdr->base.mdtype;
  138. + if (key->nsh.nsh_mdtype != NSH_M_TYPE1)
  139. + return -EPERM;
  140. + key->nsh.nsh_np = nsh_hdr->base.proto;
  141. + key->nsh.nsi = nsh_hdr->base.svc_idx;
  142. + key->nsh.nsp = nsh_hdr->base.path_hdr << 8;
  143. + key->nsh.nshc1 = nsh_hdr->ctx.nshc1;
  144. + key->nsh.nshc2 = nsh_hdr->ctx.nshc2;
  145. + key->nsh.nshc3 = nsh_hdr->ctx.nshc3;
  146. + key->nsh.nshc4 = nsh_hdr->ctx.nshc4;
  147. + return 0;
  148. +}
  149. +
  150. static __be16 parse_ethertype(struct sk_buff *skb)
  151. {
  152. struct llc_snap_hdr {
  153. @@ -461,6 +482,22 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
  154. {
  155. int error;
  156. struct ethhdr *eth;
  157. + int is_eth_nsh = 0;
  158. +
  159. + /* Extract ethernet+nsh if ethernet type is 0x894F */
  160. + eth = (struct ethhdr *)skb->data;
  161. + if (eth->h_proto == htons(ETH_P_NSH)) {
  162. + if (unlikely(parse_nsh(skb, key)))
  163. + return -EINVAL;
  164. + if (key->nsh.nsh_mdtype == NSH_M_TYPE1 && key->nsh.nsh_np == NSH_P_ETHERNET) {
  165. + __skb_pull(skb, ENCAP_ETH_LEN + NSH_M_TYPE1_LEN);
  166. + is_eth_nsh = 1;
  167. + } else {
  168. + return -EINVAL;
  169. + }
  170. + } else {
  171. + memset(&key->nsh, 0, sizeof(key->nsh));
  172. + }
  173. /* Flags are always used as part of stats */
  174. key->tp.flags = 0;
  175. @@ -685,11 +722,56 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
  176. }
  177. }
  178. }
  179. +
  180. + if (is_eth_nsh == 1) {
  181. + __skb_push(skb, ENCAP_ETH_LEN + NSH_M_TYPE1_LEN);
  182. + }
  183. +
  184. return 0;
  185. }
  186. +static void ovs_key_nsh_init(struct sw_flow_key *key) {
  187. + memset(&key->nsh, 0, sizeof(key->nsh));
  188. +}
  189. +
  190. +static int nsh_extract(struct sk_buff *skb, struct sw_flow_key *key) {
  191. + int ret;
  192. +
  193. + /* only support NSH MD tpye1 */
  194. + if (unlikely(parse_nsh(skb, key)))
  195. + return -EINVAL;
  196. + if (key->nsh.nsh_mdtype == NSH_M_TYPE1) {
  197. + __skb_pull(skb, ENCAP_ETH_LEN + NSH_M_TYPE1_LEN);
  198. + if(key->nsh.nsh_np == NSH_P_ETHERNET)
  199. + ret = key_extract(skb, key);
  200. + else
  201. + return -EINVAL;
  202. + __skb_push(skb, ENCAP_ETH_LEN + NSH_M_TYPE1_LEN);
  203. +
  204. + return ret;
  205. + } else {
  206. + ovs_key_nsh_init(key);
  207. + }
  208. +
  209. + return 0;
  210. +}
  211. +
  212. +static bool is_nsh_header(const void *tun_opts, __be16 tun_flags, struct sk_buff *skb) {
  213. + if (tun_opts && (tun_flags & TUNNEL_VXLAN_OPT)) {
  214. + /* ethernet+nsh if ethernet type is 0x894F */
  215. + struct ethhdr * eth = (struct ethhdr *)skb->data;
  216. + if (eth->h_proto == htons(ETH_P_NSH)) {
  217. + return true;
  218. + } else {
  219. + return false;
  220. + }
  221. + }
  222. + return false;
  223. +}
  224. +
  225. int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
  226. {
  227. + ovs_key_nsh_init(key);
  228. return key_extract(skb, key);
  229. }
  230. @@ -723,6 +805,15 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
  231. key->ovs_flow_hash = 0;
  232. key->recirc_id = 0;
  233. + /* Extract NSH and inner Ethernet if NSH header exists */
  234. + if (tun_info && is_nsh_header(TUN_METADATA_OPTS(key, key->tun_opts_len), key->tun_key.tun_flags, skb)) {
  235. + int ret ;
  236. + ret = nsh_extract(skb, key);
  237. + if (key->nsh.nsh_mdtype)
  238. + return ret;
  239. + } else {
  240. + ovs_key_nsh_init(key);
  241. + }
  242. return key_extract(skb, key);
  243. }
  244. @@ -739,5 +830,15 @@ int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
  245. if (err)
  246. return err;
  247. + /* Extract NSH and inner Ethernet if NSH header exists */
  248. + if (key && is_nsh_header(key->tun_opts, key->tun_key.tun_flags, skb)) {
  249. + int ret ;
  250. + ret = nsh_extract(skb, key);
  251. + if (key->nsh.nsh_mdtype)
  252. + return ret;
  253. + } else {
  254. + ovs_key_nsh_init(key);
  255. + }
  256. +
  257. return key_extract(skb, key);
  258. }
  259. diff --git a/datapath/flow.h b/datapath/flow.h
  260. index 2dd0696..bfe3423 100644
  261. --- a/datapath/flow.h
  262. +++ b/datapath/flow.h
  263. @@ -64,6 +64,7 @@ struct sw_flow_key {
  264. u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
  265. } __packed phy; /* Safe when right after 'tun_key'. */
  266. u8 tun_proto; /* Protocol of encapsulating tunnel. */
  267. + struct ovs_key_nsh nsh; /* network service header */
  268. u32 ovs_flow_hash; /* Datapath computed hash value. */
  269. u32 recirc_id; /* Recirculation ID. */
  270. struct {
  271. diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
  272. index 2dcae07..6952380 100644
  273. --- a/datapath/flow_netlink.c
  274. +++ b/datapath/flow_netlink.c
  275. @@ -284,7 +284,7 @@ size_t ovs_key_attr_size(void)
  276. /* Whenever adding new OVS_KEY_ FIELDS, we should consider
  277. * updating this function.
  278. */
  279. - BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 26);
  280. + BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 27);
  281. return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
  282. + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
  283. @@ -297,6 +297,7 @@ size_t ovs_key_attr_size(void)
  284. + nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */
  285. + nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
  286. + nla_total_size(16) /* OVS_KEY_ATTR_CT_LABELS */
  287. + + nla_total_size(40) /* OVS_KEY_ATTR_NSH */
  288. + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
  289. + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
  290. + nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
  291. @@ -336,6 +337,7 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
  292. [OVS_KEY_ATTR_PRIORITY] = { .len = sizeof(u32) },
  293. [OVS_KEY_ATTR_IN_PORT] = { .len = sizeof(u32) },
  294. [OVS_KEY_ATTR_SKB_MARK] = { .len = sizeof(u32) },
  295. + [OVS_KEY_ATTR_NSH] = { .len = sizeof(struct ovs_key_nsh) },
  296. [OVS_KEY_ATTR_ETHERNET] = { .len = sizeof(struct ovs_key_ethernet) },
  297. [OVS_KEY_ATTR_VLAN] = { .len = sizeof(__be16) },
  298. [OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },
  299. @@ -919,6 +921,35 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
  300. if (err)
  301. return err;
  302. + if (attrs & (1ULL << OVS_KEY_ATTR_NSH)) {
  303. + const struct ovs_key_nsh *nsh_key;
  304. +
  305. + nsh_key = nla_data(a[OVS_KEY_ATTR_NSH]);
  306. + SW_FLOW_KEY_MEMCPY(match, nsh.encap_eth_src,
  307. + nsh_key->encap_eth_src, ETH_ALEN, is_mask);
  308. + SW_FLOW_KEY_MEMCPY(match, nsh.encap_eth_dst,
  309. + nsh_key->encap_eth_dst, ETH_ALEN, is_mask);
  310. + SW_FLOW_KEY_PUT(match, nsh.encap_eth_type,
  311. + nsh_key->encap_eth_type, is_mask);
  312. + SW_FLOW_KEY_PUT(match, nsh.nshc1,
  313. + nsh_key->nshc1, is_mask);
  314. + SW_FLOW_KEY_PUT(match, nsh.nshc2,
  315. + nsh_key->nshc2, is_mask);
  316. + SW_FLOW_KEY_PUT(match, nsh.nshc3,
  317. + nsh_key->nshc3, is_mask);
  318. + SW_FLOW_KEY_PUT(match, nsh.nshc4,
  319. + nsh_key->nshc4, is_mask);
  320. + SW_FLOW_KEY_PUT(match, nsh.nsh_mdtype,
  321. + nsh_key->nsh_mdtype, is_mask);
  322. + SW_FLOW_KEY_PUT(match, nsh.nsh_np,
  323. + nsh_key->nsh_np, is_mask);
  324. + SW_FLOW_KEY_PUT(match, nsh.nsp,
  325. + nsh_key->nsp, is_mask);
  326. + SW_FLOW_KEY_PUT(match, nsh.nsi,
  327. + nsh_key->nsi, is_mask);
  328. + attrs &= ~(1ULL << OVS_KEY_ATTR_NSH);
  329. + }
  330. +
  331. if (attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) {
  332. const struct ovs_key_ethernet *eth_key;
  333. @@ -1434,6 +1465,26 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
  334. if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
  335. goto nla_put_failure;
  336. + if ((swkey->nsh.nsh_mdtype || is_mask)) {
  337. + struct ovs_key_nsh *nsh_key;
  338. +
  339. + nla = nla_reserve(skb, OVS_KEY_ATTR_NSH, sizeof(*nsh_key));
  340. + if (!nla)
  341. + goto nla_put_failure;
  342. + nsh_key = nla_data(nla);
  343. + memcpy(nsh_key->encap_eth_dst, output->nsh.encap_eth_dst, ETH_ALEN);
  344. + memcpy(nsh_key->encap_eth_src, output->nsh.encap_eth_src, ETH_ALEN);
  345. + nsh_key->encap_eth_type = output->nsh.encap_eth_type;
  346. + nsh_key->nsi = output->nsh.nsi;
  347. + nsh_key->nsp = output->nsh.nsp;
  348. + nsh_key->nsh_mdtype= output->nsh.nsh_mdtype;
  349. + nsh_key->nsh_np= output->nsh.nsh_np;
  350. + nsh_key->nshc1= output->nsh.nshc1;
  351. + nsh_key->nshc2 = output->nsh.nshc2;
  352. + nsh_key->nshc3 = output->nsh.nshc3;
  353. + nsh_key->nshc4 = output->nsh.nshc4;
  354. + }
  355. +
  356. if ((swkey->tun_proto || is_mask)) {
  357. const void *opts = NULL;
  358. @@ -2235,6 +2286,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
  359. [OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
  360. [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
  361. [OVS_ACTION_ATTR_POP_VLAN] = 0,
  362. + [OVS_ACTION_ATTR_PUSH_NSH] = sizeof(struct ovs_action_push_nsh),
  363. + [OVS_ACTION_ATTR_POP_NSH] = 0,
  364. [OVS_ACTION_ATTR_SET] = (u32)-1,
  365. [OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
  366. [OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
  367. @@ -2288,6 +2341,10 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
  368. break;
  369. }
  370. + case OVS_ACTION_ATTR_PUSH_NSH:
  371. + case OVS_ACTION_ATTR_POP_NSH:
  372. + break;
  373. +
  374. case OVS_ACTION_ATTR_POP_VLAN:
  375. vlan_tci = htons(0);
  376. break;
  377. diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
  378. index 44b7ce4..090843a 100644
  379. --- a/datapath/linux/compat/include/linux/openvswitch.h
  380. +++ b/datapath/linux/compat/include/linux/openvswitch.h
  381. @@ -42,6 +42,7 @@
  382. #include <linux/types.h>
  383. #include <linux/if_ether.h>
  384. +#include <asm/byteorder.h>
  385. /**
  386. * struct ovs_header - header for OVS Generic Netlink messages.
  387. @@ -332,6 +333,7 @@ enum ovs_key_attr {
  388. OVS_KEY_ATTR_ENCAP, /* Nested set of encapsulated attributes. */
  389. OVS_KEY_ATTR_PRIORITY, /* u32 skb->priority */
  390. OVS_KEY_ATTR_IN_PORT, /* u32 OVS dp port number */
  391. + OVS_KEY_ATTR_NSH, /* struct ovs_key_nsh, MD type 1 only */
  392. OVS_KEY_ATTR_ETHERNET, /* struct ovs_key_ethernet */
  393. OVS_KEY_ATTR_VLAN, /* be16 VLAN TCI */
  394. OVS_KEY_ATTR_ETHERTYPE, /* be16 Ethernet type */
  395. @@ -406,6 +408,22 @@ enum ovs_frag_type {
  396. #define OVS_FRAG_TYPE_MAX (__OVS_FRAG_TYPE_MAX - 1)
  397. +struct ovs_key_nsh {
  398. + __u8 encap_eth_dst[ETH_ALEN];
  399. + __u8 encap_eth_src[ETH_ALEN];
  400. + __u16 encap_eth_type;
  401. + __u16 pad1;
  402. + __u32 nshc1;
  403. + __u32 nshc2;
  404. + __u32 nshc3;
  405. + __u32 nshc4;
  406. + __u32 nsp;
  407. + __u8 nsi;
  408. + __u8 nsh_mdtype;
  409. + __u8 nsh_np;
  410. + __u8 pad2;
  411. +} __packed;
  412. +
  413. struct ovs_key_ethernet {
  414. __u8 eth_src[ETH_ALEN];
  415. __u8 eth_dst[ETH_ALEN];
  416. @@ -640,6 +658,151 @@ struct ovs_action_push_vlan {
  417. __be16 vlan_tci; /* 802.1Q TCI (VLAN ID and priority). */
  418. };
  419. +/*
  420. + * Network Service Header:
  421. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  422. + * |Ver|O|C|R|R|R|R|R|R| Length | MD Type | Next Proto |
  423. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  424. + * | Service Path ID | Service Index |
  425. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  426. + * Ver = The version field is used to ensure backward compatibility
  427. + * going forward with future NSH updates. It MUST be set to 0x0
  428. + * by the sender, in this first revision of NSH.
  429. + *
  430. + * O = OAM. when set to 0x1 indicates that this packet is an operations
  431. + * and management (OAM) packet. The receiving SFF and SFs nodes
  432. + * MUST examine the payload and take appropriate action.
  433. + *
  434. + * C = context. Indicates that a critical metadata TLV is present.
  435. + *
  436. + * Length : total length, in 4-byte words, of NSH including the Base
  437. + * Header, the Service Path Header and the optional variable
  438. + * TLVs.
  439. + * MD Type: indicates the format of NSH beyond the mandatory Base Header
  440. + * and the Service Path Header.
  441. + *
  442. + * Next Protocol: indicates the protocol type of the original packet. A
  443. + * new IANA registry will be created for protocol type.
  444. + *
  445. + * Service Path Identifier (SPI): identifies a service path.
  446. + * Participating nodes MUST use this identifier for Service
  447. + * Function Path selection.
  448. + *
  449. + * Service Index (SI): provides location within the SFP.
  450. + *
  451. + * [0] https://tools.ietf.org/html/draft-ietf-sfc-nsh-01
  452. + */
  453. +
  454. +struct nsh_base {
  455. +#if defined(__LITTLE_ENDIAN_BITFIELD)
  456. +
  457. + __u8 reserved_flags1:4;
  458. + __u8 context_flag:1;
  459. + __u8 oam_flag:1;
  460. + __u8 version:2;
  461. +
  462. + __u8 length:6;
  463. + __u8 reserved_flags2:2;
  464. +#elif defined(__BIG_ENDIAN_BITFIELD)
  465. +
  466. + __u8 version:2;
  467. + __u8 oam_flag:1;
  468. + __u8 context_flag:1;
  469. + __u8 reserved_flags1:4;
  470. +
  471. + __u8 reserved_flags2:2;
  472. + __u8 length:6;
  473. +#else
  474. +#error "Bitfield Endianess not defined."
  475. +#endif
  476. + __u8 mdtype;
  477. + __u8 proto;
  478. + union {
  479. + struct {
  480. + __u8 svc_path[3];
  481. + __u8 svc_idx;
  482. + };
  483. + __be32 path_hdr;
  484. + };
  485. +};
  486. +
  487. +
  488. +/**
  489. + * struct nsh_ctx - Keeps track of NSH context data
  490. + * @c<1-4>: NSH Contexts.
  491. + */
  492. +struct nsh_ctx {
  493. + __be32 nshc1;
  494. + __be32 nshc2;
  495. + __be32 nshc3;
  496. + __be32 nshc4;
  497. +};
  498. +
  499. +/**
  500. + * struct nshdr - Network Service header
  501. + * @nsh_base: Network Service Base Header.
  502. + * @nsh_ctx: Network Service Context Header.
  503. + */
  504. +struct nsh_hdr {
  505. + struct nsh_base base;
  506. + struct nsh_ctx ctx;
  507. +};
  508. +
  509. +
  510. +#define ETH_P_NSH 0x894F /* Ethertype for NSH */
  511. +
  512. +/* NSH Base Header Next Protocol */
  513. +#define NSH_P_IPV4 0x01
  514. +#define NSH_P_IPV6 0x02
  515. +#define NSH_P_ETHERNET 0x03
  516. +
  517. +/* MD Type Registry */
  518. +#define NSH_M_TYPE1 0x01
  519. +#define NSH_M_EXP1 0xFE
  520. +#define NSH_M_EXP2 0xFF
  521. +
  522. +#define NSH_DST_PORT 4790 /* UDP Port for NSH on VXLAN */
  523. +
  524. +#define NSH_M_TYPE1_LEN 24
  525. +
  526. +/* Used for masking nsp and nsi values in field nsp below */
  527. +#define NSH_M_NSP 0x00FFFFFF
  528. +#define NSH_M_NSI 0xFF000000
  529. +
  530. +/* NSH header for MD type 1. Unit is bytes */
  531. +#define NSH_PUSH_TYPE1_HEADER_SIZE 24
  532. +#define NSH_PUSH_HEADER_SIZE 256
  533. +
  534. +#define ENCAP_ETH_LEN 14
  535. +
  536. +#define ETH_NSH_TYPE1_HEADER_SIZE (NSH_PUSH_TYPE1_HEADER_SIZE + ENCAP_ETH_LEN)
  537. +/**
  538. + * struct encap_eth - encap ethernet header for ethernet NSH
  539. + * @encap_eth_src: encap ethernet source address.
  540. + * @encap_eth_src: encap ethernet destination address.
  541. + * @encap_eth_type: encap ethernet type.
  542. + */
  543. +struct encap_eth_hdr {
  544. + __u8 encap_eth_dst[ETH_ALEN];
  545. + __u8 encap_eth_src[ETH_ALEN];
  546. + __u16 encap_eth_type;
  547. +};
  548. +
  549. +struct eth_nsh_hdr {
  550. + struct encap_eth_hdr encap_eth_header;
  551. + struct nsh_hdr nsh_hdr __attribute__((packed));
  552. +};
  553. +
  554. +#define ENCAP_ETH_PUSH_HEADER_SIZE 14
  555. +/**
  556. + * struct ovs_action_push_nsh - %OVS_ACTION_ATTR_PUSH_NSH action argument.
  557. + * @header
  558. + */
  559. +struct ovs_action_push_nsh {
  560. + uint8_t nsh_mdtype;
  561. + uint8_t header[NSH_PUSH_HEADER_SIZE];
  562. +};
  563. +
  564. /* Data path hash algorithm for computing Datapath hash.
  565. *
  566. * The algorithm type only specifies the fields in a flow
  567. @@ -679,6 +842,7 @@ struct ovs_action_push_tnl {
  568. uint32_t out_port;
  569. uint32_t header_len;
  570. uint32_t tnl_type; /* For logging. */
  571. + uint32_t exts;
  572. uint8_t header[TNL_PUSH_HEADER_SIZE];
  573. };
  574. #endif
  575. @@ -804,6 +968,8 @@ enum ovs_action_attr {
  576. OVS_ACTION_ATTR_SET, /* One nested OVS_KEY_ATTR_*. */
  577. OVS_ACTION_ATTR_PUSH_VLAN, /* struct ovs_action_push_vlan. */
  578. OVS_ACTION_ATTR_POP_VLAN, /* No argument. */
  579. + OVS_ACTION_ATTR_PUSH_NSH, /* struct ovs_action_push_nsh. */
  580. + OVS_ACTION_ATTR_POP_NSH, /* No argument. */
  581. OVS_ACTION_ATTR_SAMPLE, /* Nested OVS_SAMPLE_ATTR_*. */
  582. OVS_ACTION_ATTR_RECIRC, /* u32 recirc_id. */
  583. OVS_ACTION_ATTR_HASH, /* struct ovs_action_hash. */
  584. diff --git a/include/openvswitch/automake.mk b/include/openvswitch/automake.mk
  585. index c0e276f..732b775 100644
  586. --- a/include/openvswitch/automake.mk
  587. +++ b/include/openvswitch/automake.mk
  588. @@ -29,5 +29,6 @@ openvswitchinclude_HEADERS = \
  589. include/openvswitch/uuid.h \
  590. include/openvswitch/version.h \
  591. include/openvswitch/vconn.h \
  592. - include/openvswitch/vlog.h
  593. + include/openvswitch/vlog.h \
  594. + include/openvswitch/vxlangpe.h
  595. diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h
  596. index df80dfe..84c7997 100644
  597. --- a/include/openvswitch/flow.h
  598. +++ b/include/openvswitch/flow.h
  599. @@ -99,6 +99,21 @@ struct flow {
  600. uint32_t conj_id; /* Conjunction ID. */
  601. ofp_port_t actset_output; /* Output port in action set. */
  602. + /* ETH + NSH (64-bit aligned) */
  603. + struct eth_addr encap_eth_dst; /* Encap eth destination address. */
  604. + struct eth_addr encap_eth_src; /* Encap eth source address. */
  605. + ovs_be16 encap_eth_type; /* Encap eth frame type. */
  606. + uint8_t pad2[2]; /* Pad to 64 bits. */
  607. + ovs_be32 nshc1;
  608. + ovs_be32 nshc2;
  609. + ovs_be32 nshc3;
  610. + ovs_be32 nshc4;
  611. + ovs_be32 nsp;
  612. + uint8_t nsi;
  613. + uint8_t nsh_mdtype;
  614. + uint8_t nsh_np;
  615. + uint8_t pad3;
  616. +
  617. /* L2, Order the same as in the Ethernet header! (64-bit aligned) */
  618. struct eth_addr dl_dst; /* Ethernet destination address. */
  619. struct eth_addr dl_src; /* Ethernet source address. */
  620. @@ -120,7 +135,7 @@ struct flow {
  621. struct eth_addr arp_sha; /* ARP/ND source hardware address. */
  622. struct eth_addr arp_tha; /* ARP/ND target hardware address. */
  623. ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */
  624. - ovs_be16 pad3; /* Pad to 64 bits. */
  625. + ovs_be16 pad4; /* Pad to 64 bits. */
  626. /* L4 (64-bit aligned) */
  627. ovs_be16 tp_src; /* TCP/UDP/SCTP source port/ICMP type. */
  628. @@ -135,7 +150,7 @@ BUILD_ASSERT_DECL(sizeof(struct flow_tnl) % sizeof(uint64_t) == 0);
  629. /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
  630. BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t)
  631. - == sizeof(struct flow_tnl) + 248
  632. + == sizeof(struct flow_tnl) + 288
  633. && FLOW_WC_SEQ == 36);
  634. /* Incremental points at which flow classification may be performed in
  635. diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h
  636. index 93af1b8..c5fa48a 100644
  637. --- a/include/openvswitch/match.h
  638. +++ b/include/openvswitch/match.h
  639. @@ -168,6 +168,30 @@ void match_set_nd_target(struct match *, const struct in6_addr *);
  640. void match_set_nd_target_masked(struct match *, const struct in6_addr *,
  641. const struct in6_addr *);
  642. +void match_set_nsp_masked(struct match *, ovs_be32 nsp, ovs_be32 mask);
  643. +void match_set_nsi_masked(struct match *match, uint8_t nsi, uint8_t mask);
  644. +void match_set_nsh_mdtype_masked(struct match *match, uint8_t nsh_mdtype, uint8_t mask);
  645. +void match_set_nsh_np_masked(struct match *match, uint8_t nsh_np, uint8_t mask);
  646. +void match_set_nshc1_masked(struct match *, ovs_be32 nshc1, ovs_be32 mask);
  647. +void match_set_nshc2_masked(struct match *, ovs_be32 nshc2, ovs_be32 mask);
  648. +void match_set_nshc3_masked(struct match *, ovs_be32 nshc3, ovs_be32 mask);
  649. +void match_set_nshc4_masked(struct match *, ovs_be32 nshc4, ovs_be32 mask);
  650. +void match_set_encap_eth_src_masked(struct match *match, const struct eth_addr encap_eth_src, const struct eth_addr mask);
  651. +void match_set_encap_eth_dst_masked(struct match *match, const struct eth_addr encap_eth_dst, const struct eth_addr mask);
  652. +void match_set_encap_eth_type_masked(struct match *match, ovs_be16 encap_eth_type, ovs_be16 mask);
  653. +
  654. +void match_set_nsp(struct match *, ovs_be32 nsp);
  655. +void match_set_nsi(struct match *match, uint8_t nsi);
  656. +void match_set_nsh_mdtype(struct match *match, uint8_t nsh_mdtype);
  657. +void match_set_nsh_np(struct match *match, uint8_t nsh_np);
  658. +void match_set_nshc1(struct match *, ovs_be32 nshc1);
  659. +void match_set_nshc2(struct match *, ovs_be32 nshc2);
  660. +void match_set_nshc3(struct match *, ovs_be32 nshc3);
  661. +void match_set_nshc4(struct match *, ovs_be32 nshc4);
  662. +void match_set_encap_eth_src(struct match *match, const struct eth_addr encap_eth_src);
  663. +void match_set_encap_eth_dst(struct match *match, const struct eth_addr encap_eth_dst);
  664. +void match_set_encap_eth_type(struct match *match, ovs_be16 encap_eth_type);
  665. +
  666. bool match_equal(const struct match *, const struct match *);
  667. uint32_t match_hash(const struct match *, uint32_t basis);
  668. diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
  669. index 9e569ef..fa4129c 100644
  670. --- a/include/openvswitch/meta-flow.h
  671. +++ b/include/openvswitch/meta-flow.h
  672. @@ -1801,6 +1801,180 @@ enum OVS_PACKED_ENUM mf_field_id {
  673. */
  674. MFF_ND_TLL,
  675. + /* "nsp".
  676. + *
  677. + * For a packet received including a (32-bit)
  678. + * network service header service path (nsp), the nsp is stored
  679. + * in the low 24-bits and the high bits are zeroed. For
  680. + * other packets, the value is 0.
  681. + *
  682. + * Type: be32.
  683. + * Maskable: bitwise.
  684. + * Formatting: hexadecimal.
  685. + * Prerequisites: none.
  686. + * Access: read/write.
  687. + * NXM: NXM_NX_NSP(202) since v1.1.
  688. + * OXM: none.
  689. + * Prefix lookup member: nsp.
  690. + */
  691. + MFF_NSP,
  692. +
  693. + /* "nsi".
  694. + *
  695. + * For a packet received, it includes a (8-bit)
  696. + * network service header service index (nsi).
  697. + *
  698. + * Type: u8.
  699. + * Maskable: bitwise.
  700. + * Formatting: decimal.
  701. + * Prerequisites: none.
  702. + * Access: read/write.
  703. + * NXM: NXM_NX_NSI(203) since v1.1.
  704. + * OXM: none.
  705. + * Prefix lookup member: nsi.
  706. + */
  707. + MFF_NSI,
  708. +
  709. + /* "nshc1".
  710. + *
  711. + * For a packet received including a (32-bit)
  712. + * Network Platform Context (nshc1), the nshc1 is stored
  713. + * in the 32-bits. For other packets, the value is 0.
  714. + *
  715. + * Type: be32.
  716. + * Maskable: bitwise.
  717. + * Formatting: hexadecimal.
  718. + * Prerequisites: none.
  719. + * Access: read/write.
  720. + * NXM: NXM_NX_NSH_C1(204) since v1.1.
  721. + * OXM: none.
  722. + * Prefix lookup member: nshc1.
  723. + */
  724. + MFF_NSH_C1,
  725. +
  726. + /* "nshc2".
  727. + *
  728. + * For a packet received including a (32-bit)
  729. + * Network Shared Context (nshc2), the nshc2 is stored
  730. + * in the 32-bits. For other packets, the value is 0.
  731. + *
  732. + * Type: be32.
  733. + * Maskable: bitwise.
  734. + * Formatting: hexadecimal.
  735. + * Prerequisites: none.
  736. + * Access: read/write.
  737. + * NXM: NXM_NX_NSH_C2(205) since v1.1.
  738. + * OXM: none.
  739. + * Prefix lookup member: nshc2.
  740. + */
  741. + MFF_NSH_C2,
  742. +
  743. + /* "nshc3".
  744. + *
  745. + * For a packet received via including a (32-bit)
  746. + * Service Platform Context (nshc3), the nshc3 is stored
  747. + * in the 32-bits. For other packets, the value is 0.
  748. + *
  749. + * Type: be32.
  750. + * Maskable: bitwise.
  751. + * Formatting: hexadecimal.
  752. + * Prerequisites: none.
  753. + * Access: read/write.
  754. + * NXM: NXM_NX_NSH_C3(206) since v1.1.
  755. + * OXM: none.
  756. + * Prefix lookup member: nshc3.
  757. + */
  758. + MFF_NSH_C3,
  759. +
  760. + /* "nshc4".
  761. + *
  762. + * For a packet received including a (32-bit)
  763. + * Service Shared Context (nshc4), the nshc4 is stored
  764. + * in the 32-bits. For other packets, the value is 0.
  765. + *
  766. + * Type: be32.
  767. + * Maskable: bitwise.
  768. + * Formatting: hexadecimal.
  769. + * Prerequisites: none.
  770. + * Access: read/write.
  771. + * NXM: NXM_NX_NSH_C4(207) since v1.1.
  772. + * OXM: none.
  773. + * Prefix lookup member: nshc4.
  774. + */
  775. + MFF_NSH_C4,
  776. +
  777. + /* "nsh_mdtype".
  778. + *
  779. + * For a packet received, it includes a (8-bit)
  780. + * nsh md-type field (md-type).
  781. + *
  782. + * Type: u8.
  783. + * Maskable: bitwise.
  784. + * Formatting: decimal.
  785. + * Prerequisites: none.
  786. + * Access: read/write.
  787. + * NXM: NXM_NX_NSH_MDTYPE(208) since v1.1.
  788. + * OXM: none.
  789. + */
  790. + MFF_NSH_MDTYPE,
  791. +
  792. + /* "nsh_np".
  793. + *
  794. + * For a packet received, it includes a (8-bit)
  795. + * nsh next protocol field (np).
  796. + *
  797. + * Type: u8.
  798. + * Maskable: bitwise.
  799. + * Formatting: decimal.
  800. + * Prerequisites: none.
  801. + * Access: read/write.
  802. + * NXM: NXM_NX_NSH_NP(209) since v1.1.
  803. + * OXM: none.
  804. + */
  805. + MFF_NSH_NP,
  806. +
  807. + /* "encap_eth_src".
  808. + *
  809. + * encap eth source address for Ethernet+NSH
  810. + *
  811. + * Type: MAC.
  812. + * Maskable: bitwise.
  813. + * Formatting: Ethernet.
  814. + * Prerequisites: none.
  815. + * Access: read/write.
  816. + * NXM: NXM_NX_ENCAP_ETH_SRC(210) since v1.1.
  817. + * OXM: none.
  818. + */
  819. + MFF_ENCAP_ETH_SRC,
  820. +
  821. + /* "encap_eth_dst".
  822. + *
  823. + * encap eth destination address for Ethernet+NSH
  824. + *
  825. + * Type: MAC.
  826. + * Maskable: bitwise.
  827. + * Formatting: Ethernet.
  828. + * Prerequisites: none.
  829. + * Access: read/write.
  830. + * NXM: NXM_NX_ENCAP_ETH_DST(211) since v1.1.
  831. + * OXM: none.
  832. + */
  833. + MFF_ENCAP_ETH_DST,
  834. +
  835. + /* "encap_eth_type".
  836. + *
  837. + * Encap Ethernet type.
  838. + *
  839. + * Type: be16.
  840. + * Maskable: no.
  841. + * Formatting: hexadecimal.
  842. + * Prerequisites: none.
  843. + * Access: read-only.
  844. + * NXM: NXM_NX_ENCAP_ETH_TYPE(212) since v1.1.
  845. + * OXM: none.
  846. + */
  847. + MFF_ENCAP_ETH_TYPE,
  848. +
  849. MFF_N_IDS
  850. };
  851. diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h
  852. index 01b1790..8bef529 100644
  853. --- a/include/openvswitch/ofp-actions.h
  854. +++ b/include/openvswitch/ofp-actions.h
  855. @@ -93,6 +93,10 @@
  856. OFPACT(POP_QUEUE, ofpact_null, ofpact, "pop_queue") \
  857. OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact, "fin_timeout") \
  858. \
  859. + /* NSH */ \
  860. + OFPACT(PUSH_NSH, ofpact_null, ofpact, "push_nsh") \
  861. + OFPACT(POP_NSH, ofpact_null, ofpact, "pop_nsh") \
  862. + \
  863. /* Flow table interaction. */ \
  864. OFPACT(RESUBMIT, ofpact_resubmit, ofpact, "resubmit") \
  865. OFPACT(LEARN, ofpact_learn, specs, "learn") \
  866. diff --git a/include/openvswitch/vxlangpe.h b/include/openvswitch/vxlangpe.h
  867. new file mode 100644
  868. index 0000000..b5ab7e0
  869. --- /dev/null
  870. +++ b/include/openvswitch/vxlangpe.h
  871. @@ -0,0 +1,76 @@
  872. +#ifndef __OPENVSWITCH_VXLANGPE_H
  873. +#define __OPENVSWITCH_VXLANGPE_H 1
  874. +
  875. +#include "openvswitch/types.h"
  876. +
  877. +#define u8 uint8_t
  878. +#define u32 uint8_t
  879. +#define __be32 ovs_be32
  880. +
  881. +/*
  882. + * VXLAN Generic Protocol Extension (VXLAN_F_GPE):
  883. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  884. + * |R|R|Ver|I|P|R|O| Reserved |Next Protocol |
  885. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  886. + * | VXLAN Network Identifier (VNI) | Reserved |
  887. + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  888. + *
  889. + * Ver = Version. Indicates VXLAN GPE protocol version.
  890. + *
  891. + * P = Next Protocol Bit. The P bit is set to indicate that the
  892. + * Next Protocol field is present.
  893. + *
  894. + * O = OAM Flag Bit. The O bit is set to indicate that the packet
  895. + * is an OAM packet.
  896. + *
  897. + * Next Protocol = This 8 bit field indicates the protocol header
  898. + * immediately following the VXLAN GPE header.
  899. + *
  900. + * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01
  901. + */
  902. +
  903. +struct vxlanhdr_gpe {
  904. +#ifdef WORDS_BIGENDIAN
  905. + u8 reserved_flags2:2,
  906. + version:2,
  907. + instance_applied:1,
  908. + np_applied:1,
  909. + reserved_flags1:1,
  910. + oam_flag:1;
  911. +#else
  912. + u8 oam_flag:1,
  913. + reserved_flags1:1,
  914. + np_applied:1,
  915. + instance_applied:1,
  916. + version:2,
  917. + reserved_flags2:2;
  918. +#endif
  919. + u8 reserved_flags3;
  920. + u8 reserved_flags4;
  921. + u8 next_protocol;
  922. + __be32 vx_vni;
  923. +};
  924. +
  925. +/* VXLAN-GPE header flags. */
  926. +#define VXLAN_HF_VER ((1UL <<29) | (1UL <<28))
  927. +#define VXLAN_HF_NP (1UL <<26)
  928. +#define VXLAN_HF_OAM (1UL <<24)
  929. +
  930. +#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \
  931. + 0xff)
  932. +
  933. +/* VXLAN-GPE header Next Protocol. */
  934. +#define VXLAN_GPE_NP_IPV4 0x01
  935. +#define VXLAN_GPE_NP_IPV6 0x02
  936. +#define VXLAN_GPE_NP_ETHERNET 0x03
  937. +#define VXLAN_GPE_NP_NSH 0x04
  938. +
  939. +struct vxlan_metadata {
  940. + u32 gbp;
  941. + u32 gpe;
  942. +};
  943. +
  944. +#define VXLAN_F_GPE 0x4000
  945. +#define VXLAN_HF_GPE 0x04000000
  946. +
  947. +#endif /* __OPENVSWITCH_VXLANGPE_H */
  948. diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
  949. index 44ec1a0..c779c78 100644
  950. --- a/lib/dpif-netdev.c
  951. +++ b/lib/dpif-netdev.c
  952. @@ -533,7 +533,7 @@ static int get_port_by_name(struct dp_netdev *dp, const char *devname,
  953. static void dp_netdev_free(struct dp_netdev *)
  954. OVS_REQUIRES(dp_netdev_mutex);
  955. static int do_add_port(struct dp_netdev *dp, const char *devname,
  956. - const char *type, odp_port_t port_no)
  957. + const char *type, odp_port_t port_no, uint32_t exts)
  958. OVS_REQUIRES(dp->port_mutex);
  959. static void do_del_port(struct dp_netdev *dp, struct dp_netdev_port *)
  960. OVS_REQUIRES(dp->port_mutex);
  961. @@ -1010,7 +1010,7 @@ create_dp_netdev(const char *name, const struct dpif_class *class,
  962. error = do_add_port(dp, name, dpif_netdev_port_open_type(dp->class,
  963. "internal"),
  964. - ODPP_LOCAL);
  965. + ODPP_LOCAL, 0);
  966. ovs_mutex_unlock(&dp->port_mutex);
  967. if (error) {
  968. dp_netdev_free(dp);
  969. @@ -1213,9 +1213,21 @@ hash_port_no(odp_port_t port_no)
  970. return hash_int(odp_to_u32(port_no), 0);
  971. }
  972. +static void add_vxlan_gpe_exts(struct netdev *netdev, uint32_t exts)
  973. +{
  974. + const char *type = netdev_get_type(netdev);
  975. + if (!strcmp(type, "vxlan")) {
  976. + struct netdev_tunnel_config *cfg;
  977. + cfg = netdev_get_tunnel_config(netdev);
  978. +
  979. + if(exts & (1 << OVS_VXLAN_EXT_GPE))
  980. + cfg->exts |= (1 << OVS_VXLAN_EXT_GPE);
  981. + }
  982. +}
  983. +
  984. static int
  985. port_create(const char *devname, const char *type,
  986. - odp_port_t port_no, struct dp_netdev_port **portp)
  987. + odp_port_t port_no, struct dp_netdev_port **portp, uint32_t exts)
  988. {
  989. struct netdev_saved_flags *sf;
  990. struct dp_netdev_port *port;
  991. @@ -1273,6 +1285,7 @@ port_create(const char *devname, const char *type,
  992. }
  993. }
  994. + add_vxlan_gpe_exts(netdev, exts);
  995. port = xzalloc(sizeof *port);
  996. port->port_no = port_no;
  997. port->netdev = netdev;
  998. @@ -1321,7 +1334,7 @@ out:
  999. static int
  1000. do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
  1001. - odp_port_t port_no)
  1002. + odp_port_t port_no, uint32_t exts)
  1003. OVS_REQUIRES(dp->port_mutex)
  1004. {
  1005. struct dp_netdev_port *port;
  1006. @@ -1332,7 +1345,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
  1007. return EEXIST;
  1008. }
  1009. - error = port_create(devname, type, port_no, &port);
  1010. + error = port_create(devname, type, port_no, &port, exts);
  1011. if (error) {
  1012. return error;
  1013. }
  1014. @@ -1373,7 +1386,12 @@ dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
  1015. }
  1016. if (!error) {
  1017. *port_nop = port_no;
  1018. - error = do_add_port(dp, dpif_port, netdev_get_type(netdev), port_no);
  1019. + const struct netdev_tunnel_config *cfg;
  1020. + uint32_t exts = 0;
  1021. + cfg = netdev_get_tunnel_config(netdev);
  1022. + if (cfg)
  1023. + exts = cfg->exts;
  1024. + error = do_add_port(dp, dpif_port, netdev_get_type(netdev), port_no, exts);
  1025. }
  1026. ovs_mutex_unlock(&dp->port_mutex);
  1027. @@ -2148,8 +2166,11 @@ dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
  1028. struct flow *flow)
  1029. {
  1030. odp_port_t in_port;
  1031. + enum odp_key_fitness fitness;
  1032. - if (odp_flow_key_to_flow_udpif(key, key_len, flow)) {
  1033. + fitness = odp_flow_key_to_flow_udpif(key, key_len, flow);
  1034. +
  1035. + if (fitness) {
  1036. /* This should not happen: it indicates that odp_flow_key_from_flow()
  1037. * and odp_flow_key_to_flow() disagree on the acceptable form of a
  1038. * flow. Log the problem as an error, with enough details to enable
  1039. @@ -2161,7 +2182,7 @@ dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
  1040. ds_init(&s);
  1041. odp_flow_format(key, key_len, NULL, 0, NULL, &s, true);
  1042. - VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
  1043. + VLOG_ERR("internal error parsing flow key %s (%s)", ds_cstr(&s), odp_key_fitness_to_string(fitness));
  1044. ds_destroy(&s);
  1045. }
  1046. @@ -4612,6 +4633,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
  1047. break;
  1048. }
  1049. + case OVS_ACTION_ATTR_PUSH_NSH:
  1050. + case OVS_ACTION_ATTR_POP_NSH:
  1051. case OVS_ACTION_ATTR_PUSH_VLAN:
  1052. case OVS_ACTION_ATTR_POP_VLAN:
  1053. case OVS_ACTION_ATTR_PUSH_MPLS:
  1054. diff --git a/lib/dpif.c b/lib/dpif.c
  1055. index 53958c5..86e30e0 100644
  1056. --- a/lib/dpif.c
  1057. +++ b/lib/dpif.c
  1058. @@ -1178,6 +1178,8 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_,
  1059. }
  1060. case OVS_ACTION_ATTR_HASH:
  1061. + case OVS_ACTION_ATTR_PUSH_NSH:
  1062. + case OVS_ACTION_ATTR_POP_NSH:
  1063. case OVS_ACTION_ATTR_PUSH_VLAN:
  1064. case OVS_ACTION_ATTR_POP_VLAN:
  1065. case OVS_ACTION_ATTR_PUSH_MPLS:
  1066. diff --git a/lib/flow.c b/lib/flow.c
  1067. index 375979b..e387c8b 100644
  1068. --- a/lib/flow.c
  1069. +++ b/lib/flow.c
  1070. @@ -547,6 +547,25 @@ flow_extract(struct dp_packet *packet, struct flow *flow)
  1071. miniflow_expand(&m.mf, flow);
  1072. }
  1073. +/* parse Ethernet+NSH */
  1074. +static int parse_nsh(const void *data, struct ovs_key_nsh *nsh)
  1075. +{
  1076. + memcpy(&nsh->encap_eth_dst, data, ENCAP_ETH_LEN);
  1077. + const struct nsh_hdr *nsh_hdr = (const struct nsh_hdr *)((const char *)data + ENCAP_ETH_LEN);
  1078. +
  1079. + nsh->nsh_mdtype = nsh_hdr->base.mdtype;
  1080. + if (nsh->nsh_mdtype != NSH_M_TYPE1)
  1081. + return -1;
  1082. + nsh->nsh_np = nsh_hdr->base.proto;
  1083. + nsh->nsi = nsh_hdr->base.svc_idx;
  1084. + nsh->nsp = nsh_hdr->base.path_hdr << 8;
  1085. + nsh->nshc1 = nsh_hdr->ctx.nshc1;
  1086. + nsh->nshc2 = nsh_hdr->ctx.nshc2;
  1087. + nsh->nshc3 = nsh_hdr->ctx.nshc3;
  1088. + nsh->nshc4 = nsh_hdr->ctx.nshc4;
  1089. + return 0;
  1090. +}
  1091. +
  1092. /* Caller is responsible for initializing 'dst' with enough storage for
  1093. * FLOW_U64S * 8 bytes. */
  1094. void
  1095. @@ -607,6 +626,32 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
  1096. }
  1097. }
  1098. + /* Extract Etherenet + NSH if the Ethernet type is 0x894F in packet */
  1099. + if (OVS_UNLIKELY(size < sizeof(struct eth_header)))
  1100. + goto out;
  1101. + else {
  1102. + const struct eth_header *eth = data;
  1103. + if (eth->eth_type == htons(ETH_P_NSH)) {
  1104. + /* extract Ethernet+nsh */
  1105. + struct ovs_key_nsh nsh;
  1106. + if (OVS_UNLIKELY(parse_nsh(data, &nsh)))
  1107. + goto out;
  1108. +
  1109. + /* Now only support NSH mdtype 1 */
  1110. + if (nsh.nsh_mdtype == NSH_M_TYPE1){
  1111. + /* Push all field related with Ethernet+nsh at once. */
  1112. + miniflow_push_words(mf, encap_eth_dst, &nsh,
  1113. + (sizeof (struct ovs_key_nsh)+sizeof(uint64_t) - 1) /
  1114. + sizeof(uint64_t));
  1115. + data = (const char *)data + NSH_M_TYPE1_LEN + ENCAP_ETH_LEN;
  1116. + } else
  1117. + goto out;
  1118. +
  1119. + if(nsh.nsh_np != NSH_P_ETHERNET)
  1120. + goto out;
  1121. + }
  1122. + }
  1123. +
  1124. /* Initialize packet's layer pointer and offsets. */
  1125. l2 = data;
  1126. dp_packet_reset_offsets(packet);
  1127. @@ -897,7 +942,7 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
  1128. if (flow->tunnel.gbp_flags) {
  1129. match_set_tun_gbp_flags(flow_metadata, flow->tunnel.gbp_flags);
  1130. }
  1131. - if (flow->tunnel.gpe_np != htons(0)) {
  1132. + if (flow->tunnel.gpe_np != 0) {
  1133. match_set_tun_gpe_np(flow_metadata, flow->tunnel.gpe_np);
  1134. }
  1135. if (flow->tunnel.gpe_flags) {
  1136. @@ -1316,6 +1361,21 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc,
  1137. WC_MASK_FIELD(wc, tunnel.tun_id);
  1138. }
  1139. + /* NSH fields wildcarded */
  1140. + if (flow->nsh_mdtype) {
  1141. + WC_MASK_FIELD(wc, encap_eth_src);
  1142. + WC_MASK_FIELD(wc, encap_eth_dst);
  1143. + WC_MASK_FIELD(wc, encap_eth_type);
  1144. + WC_MASK_FIELD(wc, nshc1);
  1145. + WC_MASK_FIELD(wc, nshc2);
  1146. + WC_MASK_FIELD(wc, nshc3);
  1147. + WC_MASK_FIELD(wc, nshc4);
  1148. + WC_MASK_FIELD(wc, nsh_mdtype);
  1149. + WC_MASK_FIELD(wc, nsh_np);
  1150. + WC_MASK_FIELD(wc, nsp);
  1151. + WC_MASK_FIELD(wc, nsi);
  1152. + }
  1153. +
  1154. /* metadata, regs, and conj_id wildcarded. */
  1155. WC_MASK_FIELD(wc, skb_priority);
  1156. @@ -1432,6 +1492,19 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
  1157. FLOWMAP_SET(map, ct_mark);
  1158. FLOWMAP_SET(map, ct_label);
  1159. + /* NSH fields */
  1160. + FLOWMAP_SET(map, encap_eth_src);
  1161. + FLOWMAP_SET(map, encap_eth_dst);
  1162. + FLOWMAP_SET(map, encap_eth_type);
  1163. + FLOWMAP_SET(map, nshc1);
  1164. + FLOWMAP_SET(map, nshc2);
  1165. + FLOWMAP_SET(map, nshc3);
  1166. + FLOWMAP_SET(map, nshc4);
  1167. + FLOWMAP_SET(map, nsp);
  1168. + FLOWMAP_SET(map, nsi);
  1169. + FLOWMAP_SET(map, nsh_mdtype);
  1170. + FLOWMAP_SET(map, nsh_np);
  1171. +
  1172. /* Ethertype-dependent fields. */
  1173. if (OVS_LIKELY(flow->dl_type == htons(ETH_TYPE_IP))) {
  1174. FLOWMAP_SET(map, nw_src);
  1175. @@ -2352,6 +2425,33 @@ flow_compose_l4_csum(struct dp_packet *p, const struct flow *flow,
  1176. }
  1177. }
  1178. +/* push ethernet+nsh header at the beginning of packets */
  1179. +static void
  1180. +flow_compose_nsh(struct dp_packet *p, const struct flow *flow)
  1181. +{
  1182. + struct eth_nsh_hdr *eth_nsh_header;
  1183. +
  1184. + /* Now only support mdtype1 */
  1185. + if (flow->nsh_mdtype != NSH_M_TYPE1)
  1186. + return;
  1187. +
  1188. + eth_nsh_header = dp_packet_push_uninit(p, ETH_NSH_TYPE1_HEADER_SIZE);
  1189. + eth_nsh_header->encap_eth_header.encap_eth_dst = flow->encap_eth_dst;
  1190. + eth_nsh_header->encap_eth_header.encap_eth_src = flow->encap_eth_src;
  1191. + eth_nsh_header->encap_eth_header.encap_eth_type = htons(ETH_P_NSH);
  1192. +
  1193. + memset(&eth_nsh_header->nsh_hdr, 0, sizeof (struct nsh_hdr));
  1194. + eth_nsh_header->nsh_hdr.base.length = 6;
  1195. + eth_nsh_header->nsh_hdr.base.proto = flow->nsh_np;
  1196. + eth_nsh_header->nsh_hdr.base.mdtype = flow->nsh_mdtype;
  1197. + eth_nsh_header->nsh_hdr.base.proto = flow->nsh_np;
  1198. + eth_nsh_header->nsh_hdr.base.path_hdr = flow->nsp >> 8 | flow->nsi << 24;
  1199. + eth_nsh_header->nsh_hdr.ctx.nshc1 = flow->nshc1;
  1200. + eth_nsh_header->nsh_hdr.ctx.nshc2 = flow->nshc2;
  1201. + eth_nsh_header->nsh_hdr.ctx.nshc3 = flow->nshc3;
  1202. + eth_nsh_header->nsh_hdr.ctx.nshc4 = flow->nshc4;
  1203. +}
  1204. +
  1205. /* Puts into 'b' a packet that flow_extract() would parse as having the given
  1206. * 'flow'.
  1207. *
  1208. @@ -2459,6 +2559,10 @@ flow_compose(struct dp_packet *p, const struct flow *flow)
  1209. push_mpls(p, flow->dl_type, flow->mpls_lse[--n]);
  1210. }
  1211. }
  1212. +
  1213. + if (flow->nsh_mdtype) {
  1214. + flow_compose_nsh(p, flow);
  1215. + }
  1216. }
  1217. /* Compressed flow. */
  1218. diff --git a/lib/match.c b/lib/match.c
  1219. index f19648d..daf0b87 100644
  1220. --- a/lib/match.c
  1221. +++ b/lib/match.c
  1222. @@ -878,6 +878,152 @@ match_set_nd_target_masked(struct match *match,
  1223. match->wc.masks.nd_target = *mask;
  1224. }
  1225. +void
  1226. +match_set_nsp_masked(struct match *match, ovs_be32 nsp, ovs_be32 mask)
  1227. +{
  1228. + match->wc.masks.nsp = mask;
  1229. + match->flow.nsp = nsp & mask;
  1230. +}
  1231. +
  1232. +void
  1233. +match_set_nsi_masked(struct match *match, uint8_t nsi, uint8_t mask)
  1234. +{
  1235. + match->wc.masks.nsi = mask;
  1236. + match->flow.nsi = nsi & mask;
  1237. +}
  1238. +
  1239. +void
  1240. +match_set_nsh_mdtype_masked(struct match *match, uint8_t nsh_mdtype, uint8_t mask)
  1241. +{
  1242. + match->wc.masks.nsh_mdtype = mask;
  1243. + match->flow.nsh_mdtype = nsh_mdtype & mask;
  1244. +}
  1245. +
  1246. +void
  1247. +match_set_nsh_np_masked(struct match *match, uint8_t nsh_np, uint8_t mask)
  1248. +{
  1249. + match->wc.masks.nsh_np = mask;
  1250. + match->flow.nsh_np = nsh_np & mask;
  1251. +}
  1252. +
  1253. +void
  1254. +match_set_encap_eth_src_masked(struct match *match,
  1255. + const struct eth_addr encap_eth_src,
  1256. + const struct eth_addr mask)
  1257. +{
  1258. + set_eth_masked(encap_eth_src, mask, &match->flow.encap_eth_src, &match->wc.masks.encap_eth_src);
  1259. +}
  1260. +
  1261. +void
  1262. +match_set_encap_eth_dst_masked(struct match *match,
  1263. + const struct eth_addr encap_eth_dst,
  1264. + const struct eth_addr mask)
  1265. +{
  1266. + set_eth_masked(encap_eth_dst, mask, &match->flow.encap_eth_dst, &match->wc.masks.encap_eth_dst);
  1267. +}
  1268. +
  1269. +void
  1270. +match_set_encap_eth_type_masked(struct match *match, ovs_be16 encap_eth_type, ovs_be16 mask)
  1271. +{
  1272. + match->wc.masks.encap_eth_type = mask;
  1273. + match->flow.encap_eth_type = encap_eth_type & mask;
  1274. +}
  1275. +
  1276. +void
  1277. +match_set_nshc1_masked(struct match *match, ovs_be32 nshc1, ovs_be32 mask)
  1278. +{
  1279. + match->wc.masks.nshc1 = mask;
  1280. + match->flow.nshc1 = nshc1 & mask;
  1281. +}
  1282. +
  1283. +void
  1284. +match_set_nshc2_masked(struct match *match, ovs_be32 nshc2, ovs_be32 mask)
  1285. +{
  1286. + match->wc.masks.nshc2 = mask;
  1287. + match->flow.nshc2 = nshc2 & mask;
  1288. +}
  1289. +
  1290. +void
  1291. +match_set_nshc3_masked(struct match *match, ovs_be32 nshc3, ovs_be32 mask)
  1292. +{
  1293. + match->wc.masks.nshc3 = mask;
  1294. + match->flow.nshc3 = nshc3 & mask;
  1295. +}
  1296. +
  1297. +void
  1298. +match_set_nshc4_masked(struct match *match, ovs_be32 nshc4, ovs_be32 mask)
  1299. +{
  1300. + match->wc.masks.nshc4 = mask;
  1301. + match->flow.nshc4 = nshc4 & mask;
  1302. +}
  1303. +
  1304. +void
  1305. +match_set_nsp(struct match *match, ovs_be32 nsp)
  1306. +{
  1307. + match_set_nsp_masked(match, nsp, OVS_BE32_MAX);
  1308. +}
  1309. +
  1310. +void
  1311. +match_set_nsi(struct match *match, uint8_t nsi)
  1312. +{
  1313. + match_set_nsi_masked(match, nsi, UINT8_MAX);
  1314. +}
  1315. +
  1316. +void
  1317. +match_set_nsh_mdtype(struct match *match, uint8_t nsh_mdtype)
  1318. +{
  1319. + match_set_nsh_mdtype_masked(match, nsh_mdtype, UINT8_MAX);
  1320. +}
  1321. +
  1322. +void
  1323. +match_set_nsh_np(struct match *match, uint8_t nsh_np)
  1324. +{
  1325. + match_set_nsh_np_masked(match, nsh_np, UINT8_MAX);
  1326. +}
  1327. +
  1328. +void
  1329. +match_set_nshc1(struct match *match, ovs_be32 nshc1)
  1330. +{
  1331. + match_set_nshc1_masked(match, nshc1, OVS_BE32_MAX);
  1332. +}
  1333. +
  1334. +void
  1335. +match_set_nshc2(struct match *match, ovs_be32 nshc2)
  1336. +{
  1337. + match_set_nshc2_masked(match, nshc2, OVS_BE32_MAX);
  1338. +}
  1339. +
  1340. +void
  1341. +match_set_nshc3(struct match *match, ovs_be32 nshc3)
  1342. +{
  1343. + match_set_nshc3_masked(match, nshc3, OVS_BE32_MAX);
  1344. +}
  1345. +
  1346. +void
  1347. +match_set_nshc4(struct match *match, ovs_be32 nshc4)
  1348. +{
  1349. + match_set_nshc4_masked(match, nshc4, OVS_BE32_MAX);
  1350. +}
  1351. +
  1352. +void
  1353. +match_set_encap_eth_src(struct match *match, const struct eth_addr encap_eth_src)
  1354. +{
  1355. + set_eth(encap_eth_src, &match->flow.encap_eth_src, &match->wc.masks.encap_eth_src);
  1356. +}
  1357. +
  1358. +void
  1359. +match_set_encap_eth_dst(struct match *match, const struct eth_addr encap_eth_dst)
  1360. +{
  1361. + set_eth(encap_eth_dst, &match->flow.encap_eth_dst, &match->wc.masks.encap_eth_dst);
  1362. +}
  1363. +
  1364. +void
  1365. +match_set_encap_eth_type(struct match *match, ovs_be16 encap_eth_type)
  1366. +{
  1367. + match->wc.masks.encap_eth_type = OVS_BE16_MAX;
  1368. + match->flow.encap_eth_type = encap_eth_type;
  1369. +}
  1370. +
  1371. /* Returns true if 'a' and 'b' wildcard the same fields and have the same
  1372. * values for fixed fields, otherwise false. */
  1373. bool
  1374. @@ -1171,6 +1317,49 @@ match_format(const struct match *match, struct ds *s, int priority)
  1375. format_ct_label_masked(s, &f->ct_label, &wc->masks.ct_label);
  1376. }
  1377. + if (wc->masks.nsi) {
  1378. + ds_put_format(s, "nsi=%"PRIu8",", f->nsi);
  1379. + }
  1380. +
  1381. + if (wc->masks.nsh_mdtype) {
  1382. + ds_put_format(s, "nsh_mdtype=%"PRIu8",", f->nsh_mdtype);
  1383. + }
  1384. +
  1385. + if (wc->masks.nsh_np) {
  1386. + ds_put_format(s, "nsh_np=%"PRIu8",", f->nsh_np);
  1387. + }
  1388. +
  1389. + if (wc->masks.nsp) {
  1390. + format_be32_masked(s, "nsp", f->nsp,
  1391. + wc->masks.nsp);
  1392. + }
  1393. +
  1394. + if (wc->masks.nshc1) {
  1395. + format_be32_masked(s, "nshc1", f->nshc1,
  1396. + wc->masks.nshc1);
  1397. + }
  1398. +
  1399. + if (wc->masks.nshc2) {
  1400. + format_be32_masked(s, "nshc2", f->nshc2,
  1401. + wc->masks.nshc2);
  1402. + }
  1403. +
  1404. + if (wc->masks.nshc3) {
  1405. + format_be32_masked(s, "nshc3", f->nshc3,
  1406. + wc->masks.nshc3);
  1407. + }
  1408. +
  1409. + if (wc->masks.nshc4) {
  1410. + format_be32_masked(s, "nshc4", f->nshc4,
  1411. + wc->masks.nshc4);
  1412. + }
  1413. +
  1414. + format_eth_masked(s, "encap_eth_src", f->encap_eth_src, wc->masks.encap_eth_src);
  1415. + format_eth_masked(s, "encap_eth_dst", f->encap_eth_dst, wc->masks.encap_eth_dst);
  1416. + if (wc->masks.encap_eth_type) {
  1417. + ds_put_format(s, "encap_eth_type=0x%04"PRIx16",", ntohs(f->encap_eth_type));
  1418. + }
  1419. +
  1420. if (wc->masks.dl_type) {
  1421. skip_type = true;
  1422. if (f->dl_type == htons(ETH_TYPE_IP)) {
  1423. diff --git a/lib/meta-flow.c b/lib/meta-flow.c
  1424. index 5d0721f..cf2e7b6 100644
  1425. --- a/lib/meta-flow.c
  1426. +++ b/lib/meta-flow.c
  1427. @@ -247,7 +247,28 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
  1428. }
  1429. case MFF_ACTSET_OUTPUT:
  1430. return !wc->masks.actset_output;
  1431. -
  1432. + case MFF_NSP:
  1433. + return !wc->masks.nsp;
  1434. + case MFF_NSI:
  1435. + return !wc->masks.nsi;
  1436. + case MFF_NSH_C1:
  1437. + return !wc->masks.nshc1;
  1438. + case MFF_NSH_C2:
  1439. + return !wc->masks.nshc2;
  1440. + case MFF_NSH_C3:
  1441. + return !wc->masks.nshc3;
  1442. + case MFF_NSH_C4:
  1443. + return !wc->masks.nshc4;
  1444. + case MFF_NSH_MDTYPE:
  1445. + return !wc->masks.nsh_mdtype;
  1446. + case MFF_NSH_NP:
  1447. + return !wc->masks.nsh_np;
  1448. + case MFF_ENCAP_ETH_SRC:
  1449. + return eth_addr_is_zero(wc->masks.encap_eth_src);
  1450. + case MFF_ENCAP_ETH_DST:
  1451. + return eth_addr_is_zero(wc->masks.encap_eth_dst);
  1452. + case MFF_ENCAP_ETH_TYPE:
  1453. + return !wc->masks.encap_eth_type;
  1454. case MFF_ETH_SRC:
  1455. return eth_addr_is_zero(wc->masks.dl_src);
  1456. case MFF_ETH_DST:
  1457. @@ -477,6 +498,17 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
  1458. case MFF_ICMPV6_TYPE:
  1459. case MFF_ICMPV6_CODE:
  1460. case MFF_ND_TARGET:
  1461. + case MFF_NSP:
  1462. + case MFF_NSI:
  1463. + case MFF_NSH_MDTYPE:
  1464. + case MFF_NSH_NP:
  1465. + case MFF_NSH_C1:
  1466. + case MFF_NSH_C2:
  1467. + case MFF_NSH_C3:
  1468. + case MFF_NSH_C4:
  1469. + case MFF_ENCAP_ETH_SRC:
  1470. + case MFF_ENCAP_ETH_DST:
  1471. + case MFF_ENCAP_ETH_TYPE:
  1472. case MFF_ND_SLL:
  1473. case MFF_ND_TLL:
  1474. return true;
  1475. @@ -640,6 +672,50 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
  1476. value->be128 = hton128(flow_get_xxreg(flow, mf->id - MFF_XXREG0));
  1477. break;
  1478. + case MFF_NSP:
  1479. + value->be32 = flow->nsp;
  1480. + break;
  1481. +
  1482. + case MFF_NSI:
  1483. + value->u8 = flow->nsi;
  1484. + break;
  1485. +
  1486. + case MFF_NSH_C1:
  1487. + value->be32 = flow->nshc1;
  1488. + break;
  1489. +
  1490. + case MFF_NSH_C2:
  1491. + value->be32 = flow->nshc2;
  1492. + break;
  1493. +
  1494. + case MFF_NSH_C3:
  1495. + value->be32 = flow->nshc3;
  1496. + break;
  1497. +
  1498. + case MFF_NSH_C4:
  1499. + value->be32 = flow->nshc4;
  1500. + break;
  1501. +
  1502. + case MFF_NSH_MDTYPE:
  1503. + value->u8 = flow->nsh_mdtype;
  1504. + break;
  1505. +
  1506. + case MFF_NSH_NP:
  1507. + value->u8 = flow->nsh_np;
  1508. + break;
  1509. +
  1510. + case MFF_ENCAP_ETH_SRC:
  1511. + value->mac = flow->encap_eth_src;
  1512. + break;
  1513. +
  1514. + case MFF_ENCAP_ETH_DST:
  1515. + value->mac = flow->encap_eth_dst;
  1516. + break;
  1517. +
  1518. + case MFF_ENCAP_ETH_TYPE:
  1519. + value->be16 = flow->encap_eth_type;
  1520. + break;
  1521. +
  1522. case MFF_ETH_SRC:
  1523. value->mac = flow->dl_src;
  1524. break;
  1525. @@ -1013,6 +1089,50 @@ mf_set_value(const struct mf_field *mf,
  1526. match_set_arp_sha(match, value->mac);
  1527. break;
  1528. + case MFF_NSP:
  1529. + match_set_nsp(match, value->be32);
  1530. + break;
  1531. +
  1532. + case MFF_NSI:
  1533. + match_set_nsi(match, value->u8);
  1534. + break;
  1535. +
  1536. + case MFF_NSH_MDTYPE:
  1537. + match_set_nsh_mdtype(match, value->u8);
  1538. + break;
  1539. +
  1540. + case MFF_NSH_NP:
  1541. + match_set_nsh_np(match, value->u8);
  1542. + break;
  1543. +
  1544. + case MFF_NSH_C1:
  1545. + match_set_nshc1(match, value->be32);
  1546. + break;
  1547. +
  1548. + case MFF_NSH_C2:
  1549. + match_set_nshc2(match, value->be32);
  1550. + break;
  1551. +
  1552. + case MFF_NSH_C3:
  1553. + match_set_nshc3(match, value->be32);
  1554. + break;
  1555. +
  1556. + case MFF_NSH_C4:
  1557. + match_set_nshc4(match, value->be32);
  1558. + break;
  1559. +
  1560. + case MFF_ENCAP_ETH_SRC:
  1561. + match_set_encap_eth_src(match, value->mac);
  1562. + break;
  1563. +
  1564. + case MFF_ENCAP_ETH_DST:
  1565. + match_set_encap_eth_dst(match, value->mac);
  1566. + break;
  1567. +
  1568. + case MFF_ENCAP_ETH_TYPE:
  1569. + match_set_encap_eth_type(match, value->be16);
  1570. + break;
  1571. +
  1572. case MFF_ARP_THA:
  1573. case MFF_ND_TLL:
  1574. match_set_arp_tha(match, value->mac);
  1575. @@ -1245,6 +1365,50 @@ mf_set_flow_value(const struct mf_field *mf,
  1576. flow_set_xxreg(flow, mf->id - MFF_XXREG0, ntoh128(value->be128));
  1577. break;
  1578. + case MFF_NSP:
  1579. + flow->nsp = value->be32;
  1580. + break;
  1581. +
  1582. + case MFF_NSI:
  1583. + flow->nsi = value->u8;
  1584. + break;
  1585. +
  1586. + case MFF_NSH_C1:
  1587. + flow->nshc1 = value->be32;
  1588. + break;
  1589. +
  1590. + case MFF_NSH_C2:
  1591. + flow->nshc2 = value->be32;
  1592. + break;
  1593. +
  1594. + case MFF_NSH_C3:
  1595. + flow->nshc3 = value->be32;
  1596. + break;
  1597. +
  1598. + case MFF_NSH_C4:
  1599. + flow->nshc4 = value->be32;
  1600. + break;
  1601. +
  1602. + case MFF_NSH_MDTYPE:
  1603. + flow->nsh_mdtype = value->u8;
  1604. + break;
  1605. +
  1606. + case MFF_NSH_NP:
  1607. + flow->nsh_np = value->u8;
  1608. + break;
  1609. +
  1610. + case MFF_ENCAP_ETH_SRC:
  1611. + flow->encap_eth_src = value->mac;
  1612. + break;
  1613. +
  1614. + case MFF_ENCAP_ETH_DST:
  1615. + flow->encap_eth_dst = value->mac;
  1616. + break;
  1617. +
  1618. + case MFF_ENCAP_ETH_TYPE:
  1619. + flow->encap_eth_type = value->be16;
  1620. + break;
  1621. +
  1622. case MFF_ETH_SRC:
  1623. flow->dl_src = value->mac;
  1624. break;
  1625. @@ -1689,6 +1853,52 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
  1626. match->wc.masks.arp_sha = eth_addr_zero;
  1627. break;
  1628. + case MFF_NSP:
  1629. + match_set_nsp_masked(match, htonl(0), htonl(0));
  1630. + break;
  1631. +
  1632. + case MFF_NSI:
  1633. + match_set_nsi_masked(match, 0, 0);
  1634. + break;
  1635. +
  1636. + case MFF_NSH_MDTYPE:
  1637. + match_set_nsh_mdtype_masked(match, 0, 0);
  1638. + break;
  1639. +
  1640. + case MFF_NSH_NP:
  1641. + match_set_nsh_np_masked(match, 0, 0);
  1642. + break;
  1643. +
  1644. + case MFF_NSH_C1:
  1645. + match_set_nshc1_masked(match, htonl(0), htonl(0));
  1646. + break;
  1647. +
  1648. + case MFF_NSH_C2:
  1649. + match_set_nshc2_masked(match, htonl(0), htonl(0));
  1650. + break;
  1651. +
  1652. + case MFF_NSH_C3:
  1653. + match_set_nshc3_masked(match, htonl(0), htonl(0));
  1654. + break;
  1655. +
  1656. + case MFF_NSH_C4:
  1657. + match_set_nshc4_masked(match, htonl(0), htonl(0));
  1658. + break;
  1659. +
  1660. + case MFF_ENCAP_ETH_SRC:
  1661. + match->flow.encap_eth_src= eth_addr_zero;
  1662. + match->wc.masks.encap_eth_src = eth_addr_zero;
  1663. + break;
  1664. +
  1665. + case MFF_ENCAP_ETH_DST:
  1666. + match->flow.encap_eth_dst= eth_addr_zero;
  1667. + match->wc.masks.encap_eth_dst = eth_addr_zero;
  1668. + break;
  1669. +
  1670. + case MFF_ENCAP_ETH_TYPE:
  1671. + match_set_encap_eth_type_masked(match, htons(0), htons(0));
  1672. + break;
  1673. +
  1674. case MFF_ARP_THA:
  1675. case MFF_ND_TLL:
  1676. match->flow.arp_tha = eth_addr_zero;
  1677. @@ -1890,6 +2100,50 @@ mf_set(const struct mf_field *mf,
  1678. match_set_arp_sha_masked(match, value->mac, mask->mac);
  1679. break;
  1680. + case MFF_NSP:
  1681. + match_set_nsp_masked(match, value->be32, mask->be32);
  1682. + break;
  1683. +
  1684. + case MFF_NSI:
  1685. + match_set_nsi_masked(match, value->u8, mask->u8);
  1686. + break;
  1687. +
  1688. + case MFF_NSH_MDTYPE:
  1689. + match_set_nsh_mdtype_masked(match, value->u8, mask->u8);
  1690. + break;
  1691. +
  1692. + case MFF_NSH_NP:
  1693. + match_set_nsh_np_masked(match, value->u8, mask->u8);
  1694. + break;
  1695. +
  1696. + case MFF_NSH_C1:
  1697. + match_set_nshc1_masked(match, value->be32, mask->be32);
  1698. + break;
  1699. +
  1700. + case MFF_NSH_C2:
  1701. + match_set_nshc2_masked(match, value->be32, mask->be32);
  1702. + break;
  1703. +
  1704. + case MFF_NSH_C3:
  1705. + match_set_nshc3_masked(match, value->be32, mask->be32);
  1706. + break;
  1707. +
  1708. + case MFF_NSH_C4:
  1709. + match_set_nshc4_masked(match, value->be32, mask->be32);
  1710. + break;
  1711. +
  1712. + case MFF_ENCAP_ETH_SRC:
  1713. + match_set_encap_eth_src_masked(match, value->mac, mask->mac);
  1714. + break;
  1715. +
  1716. + case MFF_ENCAP_ETH_DST:
  1717. + match_set_encap_eth_dst_masked(match, value->mac, mask->mac);
  1718. + break;
  1719. +
  1720. + case MFF_ENCAP_ETH_TYPE:
  1721. + match_set_encap_eth_type_masked(match, value->be16, mask->be16);
  1722. + break;
  1723. +
  1724. case MFF_ARP_THA:
  1725. case MFF_ND_TLL:
  1726. match_set_arp_tha_masked(match, value->mac, mask->mac);
  1727. diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
  1728. index ce2582f..2fe2722 100644
  1729. --- a/lib/netdev-native-tnl.c
  1730. +++ b/lib/netdev-native-tnl.c
  1731. @@ -44,6 +44,7 @@
  1732. #include "unaligned.h"
  1733. #include "unixctl.h"
  1734. #include "openvswitch/vlog.h"
  1735. +#include "openvswitch/vxlangpe.h"
  1736. VLOG_DEFINE_THIS_MODULE(native_tnl);
  1737. static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5);
  1738. @@ -209,6 +210,9 @@ netdev_tnl_push_udp_header(struct dp_packet *packet,
  1739. struct udp_header *udp;
  1740. int ip_tot_size;
  1741. + if ((data->tnl_type == OVS_VPORT_TYPE_VXLAN) && (data->exts & (1 << VXLAN_GPE_POP_ETH)))
  1742. + dp_packet_reset_packet(packet, ENCAP_ETH_LEN);
  1743. +
  1744. udp = netdev_tnl_push_ip_header(packet, data->header, data->header_len, &ip_tot_size);
  1745. /* set udp src port */
  1746. @@ -478,6 +482,8 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
  1747. struct flow_tnl *tnl = &md->tunnel;
  1748. struct vxlanhdr *vxh;
  1749. unsigned int hlen;
  1750. + ovs_be32 flag;
  1751. + ovs_be32 vni;
  1752. pkt_metadata_init_tnl(md);
  1753. if (VXLAN_HLEN > dp_packet_l4_size(packet)) {
  1754. @@ -489,17 +495,59 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
  1755. goto err;
  1756. }
  1757. - if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
  1758. - (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
  1759. - VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
  1760. - ntohl(get_16aligned_be32(&vxh->vx_flags)),
  1761. - ntohl(get_16aligned_be32(&vxh->vx_vni)));
  1762. - goto err;
  1763. - }
  1764. - tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
  1765. - tnl->flags |= FLOW_TNL_F_KEY;
  1766. + /* vxlan-gpe packets*/
  1767. + flag = get_16aligned_be32(&vxh->vx_flags);
  1768. + vni = get_16aligned_be32(&vxh->vx_vni);
  1769. +
  1770. + if (flag & VXLAN_HF_GPE) {
  1771. + flag &= ~VXLAN_GPE_USED_BITS;
  1772. + if ((flag & ~VXLAN_GPE_USED_BITS) ||
  1773. + (vni & htonl(0xff))) {
  1774. +
  1775. + VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n for vxlan-gpe",
  1776. + ntohl(flag),
  1777. + ntohl(vni));
  1778. + goto err;
  1779. + }
  1780. +
  1781. + struct vxlanhdr_gpe *gpe;
  1782. +
  1783. + gpe = (struct vxlanhdr_gpe *)vxh;
  1784. + tnl->gpe_np = gpe->next_protocol;
  1785. - dp_packet_reset_packet(packet, hlen + VXLAN_HLEN);
  1786. + /* Drop the OAM packets */
  1787. + if (gpe->oam_flag)
  1788. + goto err;
  1789. +
  1790. + tnl->tun_id = htonll(ntohl(vni) >> 8);
  1791. + tnl->flags |= FLOW_TNL_F_KEY;
  1792. +
  1793. + if (tnl->gpe_np == VXLAN_GPE_NP_NSH) {
  1794. + /* Add a faked ethernet header which type is 0x894F, so the OVS
  1795. + * can receive frame starting with ethernet header.
  1796. + */
  1797. + struct eth_header * encap_eth;
  1798. + struct eth_header * eth = dp_packet_l2(packet);
  1799. +
  1800. + memmove((char *)eth + hlen + VXLAN_HLEN - ENCAP_ETH_LEN, (char *)eth + hlen + VXLAN_HLEN + NSH_PUSH_TYPE1_HEADER_SIZE, 2 * ETH_ADDR_LEN);
  1801. + dp_packet_reset_packet(packet, hlen + VXLAN_HLEN - ENCAP_ETH_LEN);
  1802. + encap_eth = dp_packet_data(packet);
  1803. + encap_eth->eth_type = htons(ETH_P_NSH);
  1804. + } else
  1805. + dp_packet_reset_packet(packet, hlen + VXLAN_HLEN);
  1806. + } else {
  1807. + if (flag != htonl(VXLAN_FLAGS) ||
  1808. + (vni & htonl(0xff))) {
  1809. + VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
  1810. + ntohl(flag),
  1811. + ntohl(vni));
  1812. + goto err;
  1813. + }
  1814. + tnl->tun_id = htonll(ntohl(vni) >> 8);
  1815. + tnl->flags |= FLOW_TNL_F_KEY;
  1816. +
  1817. + dp_packet_reset_packet(packet, hlen + VXLAN_HLEN);
  1818. + }
  1819. return packet;
  1820. err:
  1821. @@ -522,8 +570,27 @@ netdev_vxlan_build_header(const struct netdev *netdev,
  1822. vxh = udp_build_header(tnl_cfg, data, params);
  1823. - put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
  1824. - put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
  1825. + if(tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GPE)) {
  1826. + struct vxlanhdr_gpe *gpe;
  1827. +
  1828. + gpe = (struct vxlanhdr_gpe *)vxh;
  1829. + put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS | VXLAN_HF_GPE));
  1830. + put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
  1831. +
  1832. + if (!params->flow->tunnel.gpe_np)
  1833. + return -1;
  1834. + else
  1835. + gpe->next_protocol = params->flow->tunnel.gpe_np;
  1836. +
  1837. + if (params->flow->tunnel.gpe_flags & 0x01)
  1838. + gpe->oam_flag = 1;
  1839. +
  1840. + if (params->flow->tunnel.gpe_np == VXLAN_GPE_NP_NSH)
  1841. + data->exts |= 1 << VXLAN_GPE_POP_ETH;
  1842. + } else {
  1843. + put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
  1844. + put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
  1845. + }
  1846. ovs_mutex_unlock(&dev->mutex);
  1847. data->header_len += sizeof *vxh;
  1848. diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
  1849. index cff0f5c..841a070 100644
  1850. --- a/lib/netdev-vport.c
  1851. +++ b/lib/netdev-vport.c
  1852. @@ -525,9 +525,15 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
  1853. ext = strtok_r(str, ",", &save_ptr);
  1854. while (ext) {
  1855. if (!strcmp(type, "vxlan") && !strcmp(ext, "gbp")) {
  1856. - tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
  1857. + if (tnl_cfg.exts & (1 << OVS_VXLAN_EXT_GPE))
  1858. + VLOG_WARN("VXLAN_GPE extension exists, VxLAN_GBP extension can't be added.");
  1859. + else
  1860. + tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
  1861. } else if (!strcmp(type, "vxlan") && !strcmp(ext, "gpe")) {
  1862. - tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GPE);
  1863. + if (tnl_cfg.exts & (1 << OVS_VXLAN_EXT_GBP))
  1864. + VLOG_WARN("VXLAN_GBP extension exists, VxLAN_GPE extension can't be added.");
  1865. + else
  1866. + tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GPE);
  1867. } else {
  1868. VLOG_WARN("%s: unknown extension '%s'", name, ext);
  1869. }
  1870. diff --git a/lib/netdev-vport.h b/lib/netdev-vport.h
  1871. index 048aa6e..b19cbd2 100644
  1872. --- a/lib/netdev-vport.h
  1873. +++ b/lib/netdev-vport.h
  1874. @@ -48,6 +48,12 @@ enum { NETDEV_VPORT_NAME_BUFSIZE = 16 };
  1875. #else
  1876. enum { NETDEV_VPORT_NAME_BUFSIZE = 256 };
  1877. #endif
  1878. +
  1879. +enum OVS_ACTION_PUSH_VXLAN_EXTS {
  1880. + VXLAN_GPE_POP_ETH, /* Pop ethernet header when the field next_proto
  1881. + * is 4 in vxlan-gpe header
  1882. + */
  1883. +};
  1884. const char *netdev_vport_get_dpif_port(const struct netdev *,
  1885. char namebuf[], size_t bufsize)
  1886. OVS_WARN_UNUSED_RESULT;
  1887. diff --git a/lib/nx-match.c b/lib/nx-match.c
  1888. index 65d7ee3..0c108f4 100644
  1889. --- a/lib/nx-match.c
  1890. +++ b/lib/nx-match.c
  1891. @@ -948,6 +948,24 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
  1892. ofputil_port_to_ofp11(flow->actset_output));
  1893. }
  1894. + /* NSH */
  1895. + nxm_put_32m(b, MFF_NSP, oxm, flow->nsp, match->wc.masks.nsp);
  1896. + nxm_put_8m(b, MFF_NSI, oxm, flow->nsi, match->wc.masks.nsi);
  1897. + nxm_put_8m(b, MFF_NSH_MDTYPE, oxm, flow->nsh_mdtype, match->wc.masks.nsh_mdtype);
  1898. + nxm_put_8m(b, MFF_NSH_NP, oxm, flow->nsh_np, match->wc.masks.nsh_np);
  1899. + nxm_put_32m(b, MFF_NSH_C1, oxm, flow->nshc1, match->wc.masks.nshc1);
  1900. + nxm_put_32m(b, MFF_NSH_C2, oxm, flow->nshc2, match->wc.masks.nshc2);
  1901. + nxm_put_32m(b, MFF_NSH_C3, oxm, flow->nshc3, match->wc.masks.nshc3);
  1902. + nxm_put_32m(b, MFF_NSH_C4, oxm, flow->nshc4, match->wc.masks.nshc4);
  1903. +
  1904. + nxm_put_eth_masked(b, MFF_ENCAP_ETH_SRC, oxm,
  1905. + flow->encap_eth_src, match->wc.masks.encap_eth_src);
  1906. + nxm_put_eth_masked(b, MFF_ENCAP_ETH_DST, oxm,
  1907. + flow->encap_eth_dst, match->wc.masks.encap_eth_dst);
  1908. + nxm_put_16m(b, MFF_ENCAP_ETH_TYPE, oxm,
  1909. + ofputil_dl_type_to_openflow(flow->encap_eth_type),
  1910. + match->wc.masks.encap_eth_type);
  1911. +
  1912. /* Ethernet. */
  1913. nxm_put_eth_masked(b, MFF_ETH_SRC, oxm,
  1914. flow->dl_src, match->wc.masks.dl_src);
  1915. diff --git a/lib/odp-execute.c b/lib/odp-execute.c
  1916. index 5a43904..20e3106 100644
  1917. --- a/lib/odp-execute.c
  1918. +++ b/lib/odp-execute.c
  1919. @@ -336,6 +336,7 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
  1920. case OVS_KEY_ATTR_CT_ZONE:
  1921. case OVS_KEY_ATTR_CT_MARK:
  1922. case OVS_KEY_ATTR_CT_LABELS:
  1923. + case OVS_KEY_ATTR_NSH:
  1924. case __OVS_KEY_ATTR_MAX:
  1925. default:
  1926. OVS_NOT_REACHED();
  1927. @@ -432,6 +433,7 @@ odp_execute_masked_set_action(struct dp_packet *packet,
  1928. case OVS_KEY_ATTR_ETHERTYPE:
  1929. case OVS_KEY_ATTR_IN_PORT:
  1930. case OVS_KEY_ATTR_VLAN:
  1931. + case OVS_KEY_ATTR_NSH:
  1932. case OVS_KEY_ATTR_ICMP:
  1933. case OVS_KEY_ATTR_ICMPV6:
  1934. case OVS_KEY_ATTR_TCP_FLAGS:
  1935. @@ -497,6 +499,8 @@ requires_datapath_assistance(const struct nlattr *a)
  1936. case OVS_ACTION_ATTR_SET:
  1937. case OVS_ACTION_ATTR_SET_MASKED:
  1938. + case OVS_ACTION_ATTR_PUSH_NSH:
  1939. + case OVS_ACTION_ATTR_POP_NSH:
  1940. case OVS_ACTION_ATTR_PUSH_VLAN:
  1941. case OVS_ACTION_ATTR_POP_VLAN:
  1942. case OVS_ACTION_ATTR_SAMPLE:
  1943. @@ -586,6 +590,21 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
  1944. }
  1945. break;
  1946. + case OVS_ACTION_ATTR_PUSH_NSH: {
  1947. + const void *push_nsh_hdr = nl_attr_get(a);
  1948. +
  1949. + for (i = 0; i < cnt; i++) {
  1950. + push_nsh(packets[i], push_nsh_hdr);
  1951. + }
  1952. + break;
  1953. + }
  1954. +
  1955. + case OVS_ACTION_ATTR_POP_NSH:
  1956. + for (i = 0; i < cnt; i++) {
  1957. + pop_nsh(packets[i]);
  1958. + }
  1959. + break;
  1960. +
  1961. case OVS_ACTION_ATTR_PUSH_MPLS: {
  1962. const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
  1963. diff --git a/lib/odp-util.c b/lib/odp-util.c
  1964. index b9e8aa7..97b4e94 100644
  1965. --- a/lib/odp-util.c
  1966. +++ b/lib/odp-util.c
  1967. @@ -70,7 +70,8 @@ static void format_odp_key_attr(const struct nlattr *a,
  1968. const struct nlattr *ma,
  1969. const struct hmap *portno_names, struct ds *ds,
  1970. bool verbose);
  1971. -
  1972. +static void format_eth(struct ds *ds, const char *name, const struct eth_addr key,
  1973. + const struct eth_addr *mask, bool verbose);
  1974. struct geneve_scan {
  1975. struct geneve_opt d[63];
  1976. int len;
  1977. @@ -113,6 +114,8 @@ odp_action_len(uint16_t type)
  1978. case OVS_ACTION_ATTR_USERSPACE: return ATTR_LEN_VARIABLE;
  1979. case OVS_ACTION_ATTR_PUSH_VLAN: return sizeof(struct ovs_action_push_vlan);
  1980. case OVS_ACTION_ATTR_POP_VLAN: return 0;
  1981. + case OVS_ACTION_ATTR_PUSH_NSH: return sizeof(struct ovs_action_push_nsh);
  1982. + case OVS_ACTION_ATTR_POP_NSH: return 0;
  1983. case OVS_ACTION_ATTR_PUSH_MPLS: return sizeof(struct ovs_action_push_mpls);
  1984. case OVS_ACTION_ATTR_POP_MPLS: return sizeof(ovs_be16);
  1985. case OVS_ACTION_ATTR_RECIRC: return sizeof(uint32_t);
  1986. @@ -148,6 +151,7 @@ ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize)
  1987. case OVS_KEY_ATTR_CT_LABELS: return "ct_label";
  1988. case OVS_KEY_ATTR_TUNNEL: return "tunnel";
  1989. case OVS_KEY_ATTR_IN_PORT: return "in_port";
  1990. + case OVS_KEY_ATTR_NSH: return "nsh";
  1991. case OVS_KEY_ATTR_ETHERNET: return "eth";
  1992. case OVS_KEY_ATTR_VLAN: return "vlan";
  1993. case OVS_KEY_ATTR_ETHERTYPE: return "eth_type";
  1994. @@ -376,6 +380,31 @@ format_vlan_tci(struct ds *ds, ovs_be16 tci, ovs_be16 mask, bool verbose)
  1995. }
  1996. static void
  1997. +format_nsh(struct ds *ds, const struct ovs_action_push_nsh * nsh)
  1998. +{
  1999. + const struct eth_nsh_hdr *eth_nsh_header = (struct eth_nsh_hdr *)nsh->header;
  2000. + format_eth(ds, "encap_eth_src",
  2001. + eth_nsh_header->encap_eth_header.encap_eth_src,
  2002. + NULL, true);
  2003. + format_eth(ds, "encap_eth_dst",
  2004. + eth_nsh_header->encap_eth_header.encap_eth_dst,
  2005. + NULL, true);
  2006. + ds_put_format(ds, "encap_eth_type=0x%04"PRIx16",",
  2007. + ntohs(eth_nsh_header->encap_eth_header.encap_eth_type));
  2008. + ds_put_format(ds, "nsh_mdtype=%"PRIu8",nsh_np=%"PRIu8",nsp=%"PRIu32
  2009. + ",nsi=%"PRIu8",nshc1=%"PRIu32",nshc2=%"PRIu32
  2010. + ",nshc3=%"PRIu32",nshc4=%"PRIu32")",
  2011. + eth_nsh_header->nsh_hdr.base.mdtype,
  2012. + eth_nsh_header->nsh_hdr.base.proto,
  2013. + ntohl(eth_nsh_header->nsh_hdr.base.path_hdr) >> 8,
  2014. + ntohl(eth_nsh_header->nsh_hdr.base.path_hdr) & 0xFF,
  2015. + ntohl(eth_nsh_header->nsh_hdr.ctx.nshc1),
  2016. + ntohl(eth_nsh_header->nsh_hdr.ctx.nshc2),
  2017. + ntohl(eth_nsh_header->nsh_hdr.ctx.nshc3),
  2018. + ntohl(eth_nsh_header->nsh_hdr.ctx.nshc4));
  2019. +}
  2020. +
  2021. +static void
  2022. format_mpls_lse(struct ds *ds, ovs_be32 mpls_lse)
  2023. {
  2024. ds_put_format(ds, "label=%"PRIu32",tc=%d,ttl=%d,bos=%d",
  2025. @@ -503,7 +532,7 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
  2026. gnh->oam ? "oam," : "",
  2027. gnh->critical ? "crit," : "",
  2028. ntohl(get_16aligned_be32(&gnh->vni)) >> 8);
  2029. -
  2030. +
  2031. if (gnh->opt_len) {
  2032. ds_put_cstr(ds, ",options(");
  2033. format_geneve_opts(gnh->options, NULL, gnh->opt_len * 4,
  2034. @@ -763,6 +792,7 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
  2035. {
  2036. int expected_len;
  2037. enum ovs_action_attr type = nl_attr_type(a);
  2038. + const struct ovs_action_push_nsh *nsh;
  2039. size_t size;
  2040. expected_len = odp_action_len(nl_attr_type(a));
  2041. @@ -841,6 +871,14 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
  2042. case OVS_ACTION_ATTR_POP_VLAN:
  2043. ds_put_cstr(ds, "pop_vlan");
  2044. break;
  2045. + case OVS_ACTION_ATTR_PUSH_NSH:
  2046. + nsh = nl_attr_get(a);
  2047. + ds_put_cstr(ds, "push_nsh(");
  2048. + format_nsh(ds, nsh);
  2049. + break;
  2050. + case OVS_ACTION_ATTR_POP_NSH:
  2051. + ds_put_cstr(ds, "pop_nsh");
  2052. + break;
  2053. case OVS_ACTION_ATTR_PUSH_MPLS: {
  2054. const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
  2055. ds_put_cstr(ds, "push_mpls(");
  2056. @@ -1646,6 +1684,53 @@ parse_odp_action(const char *s, const struct simap *port_names,
  2057. }
  2058. {
  2059. + struct ovs_action_push_nsh push;
  2060. + struct eth_nsh_hdr *eth_nsh_header = (struct eth_nsh_hdr *)push.header;
  2061. + ovs_be32 nsp, nshc1,nshc2,nshc3,nshc4;
  2062. + uint8_t nsi, nsh_mdtype, nsh_np;
  2063. + int n = -1;
  2064. +
  2065. + if (ovs_scan_len(s, &n, "push_nsh(encap_eth_dst="ETH_ADDR_SCAN_FMT
  2066. + ",encap_eth_src="ETH_ADDR_SCAN_FMT
  2067. + ",encap_eth_type=0x%"SCNx16
  2068. + ",nsh_mdtype=%"SCNi8",nsh_np=%"SCNi8",nsp=0x%"SCNx32
  2069. + ",nsi=%"SCNi8",nshc1=0x%"SCNx32",nshc2=0x%"SCNx32
  2070. + ",nshc3=0x%"SCNx32",nshc4=0x%"SCNx32"))",
  2071. + ETH_ADDR_SCAN_ARGS(eth_nsh_header->encap_eth_header.encap_eth_dst),
  2072. + ETH_ADDR_SCAN_ARGS(eth_nsh_header->encap_eth_header.encap_eth_src),
  2073. + &eth_nsh_header->encap_eth_header.encap_eth_type,
  2074. + &nsh_mdtype, &nsh_np,
  2075. + &nsp, &nsi,
  2076. + &nshc1, &nshc2,
  2077. + &nshc3, &nshc4)) {
  2078. + eth_nsh_header->encap_eth_header.encap_eth_type = htons(eth_nsh_header->encap_eth_header.encap_eth_type);
  2079. + if (nsh_mdtype == NSH_M_TYPE1) {
  2080. + eth_nsh_header->encap_eth_header.encap_eth_type = htons(ETH_P_NSH);
  2081. + eth_nsh_header->nsh_hdr.base.mdtype = NSH_M_TYPE1;
  2082. + eth_nsh_header->nsh_hdr.base.version = 0x01;
  2083. + eth_nsh_header->nsh_hdr.base.length = 6;
  2084. + eth_nsh_header->nsh_hdr.base.proto = nsh_np;
  2085. + eth_nsh_header->nsh_hdr.base.path_hdr= nsp;
  2086. + eth_nsh_header->nsh_hdr.base.svc_idx = nsi;
  2087. + eth_nsh_header->nsh_hdr.ctx.nshc1=nshc1;
  2088. + eth_nsh_header->nsh_hdr.ctx.nshc2=nshc2;
  2089. + eth_nsh_header->nsh_hdr.ctx.nshc3=nshc3;
  2090. + eth_nsh_header->nsh_hdr.ctx.nshc4=nshc4;
  2091. + push.nsh_mdtype = NSH_M_TYPE1;
  2092. + nl_msg_put_unspec(actions, OVS_ACTION_ATTR_PUSH_NSH,
  2093. + &push, sizeof push);
  2094. + }
  2095. +
  2096. + return n;
  2097. + }
  2098. + }
  2099. +
  2100. + if (!strncmp(s, "pop_nsh", 7)) {
  2101. + nl_msg_put_flag(actions, OVS_ACTION_ATTR_POP_NSH);
  2102. + return 7;
  2103. + }
  2104. +
  2105. + {
  2106. double percentage;
  2107. int n = -1;
  2108. @@ -1787,6 +1872,7 @@ static const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] =
  2109. .next = ovs_tun_key_attr_lens,
  2110. .next_max = OVS_TUNNEL_KEY_ATTR_MAX },
  2111. [OVS_KEY_ATTR_IN_PORT] = { .len = 4 },
  2112. + [OVS_KEY_ATTR_NSH] = { .len = sizeof(struct ovs_key_nsh) },
  2113. [OVS_KEY_ATTR_ETHERNET] = { .len = sizeof(struct ovs_key_ethernet) },
  2114. [OVS_KEY_ATTR_VLAN] = { .len = 2 },
  2115. [OVS_KEY_ATTR_ETHERTYPE] = { .len = 2 },
  2116. @@ -1924,7 +2010,7 @@ odp_tun_key_from_attr__(const struct nlattr *attr,
  2117. };
  2118. struct nlattr *ext[ARRAY_SIZE(vxlan_opts_policy)];
  2119. - if (!nl_parse_nested(a, vxlan_opts_policy, ext, ARRAY_SIZE(ext))) {
  2120. + if (!nl_parse_nested(a, vxlan_opts_policy, ext, ARRAY_SIZE(vxlan_opts_policy))) {
  2121. return ODP_FIT_ERROR;
  2122. }
  2123. @@ -2173,6 +2259,23 @@ format_be64(struct ds *ds, const char *name, ovs_be64 key,
  2124. }
  2125. static void
  2126. +format_be32(struct ds *ds, const char *name, ovs_be32 key,
  2127. + const ovs_be32 *mask, bool verbose)
  2128. +{
  2129. + bool mask_empty = mask && !*mask;
  2130. +
  2131. + if (verbose || !mask_empty) {
  2132. + bool mask_full = !mask || *mask == OVS_BE32_MAX;
  2133. +
  2134. + ds_put_format(ds, "%s=%"PRIx32, name, ntohl(key));
  2135. + if (!mask_full) { /* Partially masked. */
  2136. + ds_put_format(ds, "/%#"PRIx32, ntohl(*mask));
  2137. + }
  2138. + ds_put_char(ds, ',');
  2139. + }
  2140. +}
  2141. +
  2142. +static void
  2143. format_ipv4(struct ds *ds, const char *name, ovs_be32 key,
  2144. const ovs_be32 *mask, bool verbose)
  2145. {
  2146. @@ -2827,6 +2930,25 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
  2147. }
  2148. break;
  2149. + case OVS_KEY_ATTR_NSH: {
  2150. + const struct ovs_key_nsh *mask = ma ? nl_attr_get(ma) : NULL;
  2151. + const struct ovs_key_nsh *key = nl_attr_get(a);
  2152. +
  2153. + format_eth(ds, "encap_eth_src", key->encap_eth_src, MASK(mask, encap_eth_src), verbose);
  2154. + format_eth(ds, "encap_eth_dst", key->encap_eth_dst, MASK(mask, encap_eth_dst), verbose);
  2155. + format_be16x(ds, "encap_eth_type", key->encap_eth_type, MASK(mask, encap_eth_type), verbose);
  2156. + format_u8u(ds, "nsi", key->nsi, MASK(mask, nsi), verbose);
  2157. + format_be32(ds, "nsp", key->nsp, MASK(mask, nsp), verbose);
  2158. + format_u8u(ds, "nsh_mdtype", key->nsh_mdtype, MASK(mask, nsh_mdtype), verbose);
  2159. + format_u8u(ds, "nsh_np", key->nsh_np, MASK(mask, nsh_np), verbose);
  2160. + format_be32(ds, "nshc1", key->nshc1, MASK(mask, nshc1), verbose);
  2161. + format_be32(ds, "nshc2", key->nshc2, MASK(mask, nshc2), verbose);
  2162. + format_be32(ds, "nshc3", key->nshc3, MASK(mask, nshc3), verbose);
  2163. + format_be32(ds, "nshc4", key->nshc4, MASK(mask, nshc4), verbose);
  2164. + ds_chomp(ds, ',');
  2165. + break;
  2166. + }
  2167. +
  2168. case OVS_KEY_ATTR_ETHERNET: {
  2169. const struct ovs_key_ethernet *mask = ma ? nl_attr_get(ma) : NULL;
  2170. const struct ovs_key_ethernet *key = nl_attr_get(a);
  2171. @@ -3219,6 +3341,27 @@ scan_eth(const char *s, struct eth_addr *key, struct eth_addr *mask)
  2172. }
  2173. static int
  2174. +scan_nsp(const char *s, uint32_t *key, uint32_t *mask)
  2175. +{
  2176. + int n;
  2177. +
  2178. + if (ovs_scan(s, "%"SCNi32"%n", key, &n)) {
  2179. + int len = n;
  2180. + *key = htonl(*key);
  2181. + if (mask) {
  2182. + if (ovs_scan(s + len, "/%"SCNi32"%n", mask, &n)) {
  2183. + len += n;
  2184. + *mask =htonl(*mask);
  2185. + } else {
  2186. + *mask = UINT32_MAX;
  2187. + }
  2188. + }
  2189. + return len;
  2190. + }
  2191. + return 0;
  2192. +}
  2193. +
  2194. +static int
  2195. scan_ipv4(const char *s, ovs_be32 *key, ovs_be32 *mask)
  2196. {
  2197. int n;
  2198. @@ -4158,6 +4301,20 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
  2199. SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr);
  2200. } SCAN_END_NESTED();
  2201. + SCAN_BEGIN("nsh(", struct ovs_key_nsh) {
  2202. + SCAN_FIELD("encap_eth_dst=", eth, encap_eth_dst);
  2203. + SCAN_FIELD("encap_eth_src=", eth, encap_eth_src);
  2204. + SCAN_FIELD("encap_eth_type=", be16, encap_eth_type);
  2205. + SCAN_FIELD("nsh_mdtype=", u8, nsh_mdtype);
  2206. + SCAN_FIELD("nsh_np=", u8, nsh_np);
  2207. + SCAN_FIELD("nsp=", nsp, nsp);
  2208. + SCAN_FIELD("nsi=", u8, nsi);
  2209. + SCAN_FIELD("nshc1=", u32, nshc1);
  2210. + SCAN_FIELD("nshc2=", u32, nshc2);
  2211. + SCAN_FIELD("nshc3=", u32, nshc3);
  2212. + SCAN_FIELD("nshc4=", u32, nshc4);
  2213. + } SCAN_END(OVS_KEY_ATTR_NSH);
  2214. +
  2215. SCAN_SINGLE_PORT("in_port(", uint32_t, OVS_KEY_ATTR_IN_PORT);
  2216. SCAN_BEGIN("eth(", struct ovs_key_ethernet) {
  2217. @@ -4360,11 +4517,30 @@ union ovs_key_tp {
  2218. static void get_tp_key(const struct flow *, union ovs_key_tp *);
  2219. static void put_tp_key(const union ovs_key_tp *, struct flow *);
  2220. +void
  2221. +get_nsh_key(const struct flow *flow, struct ovs_key_nsh *nsh)
  2222. +{
  2223. + nsh->nsi = flow->nsi;
  2224. + nsh->nsp = flow->nsp;
  2225. + nsh->nsh_mdtype = flow->nsh_mdtype;
  2226. + nsh->nsh_np = flow->nsh_np;
  2227. + nsh->nshc1 = flow->nshc1;
  2228. + nsh->nshc2 = flow->nshc2;
  2229. + nsh->nshc3 = flow->nshc3;
  2230. + nsh->nshc4 = flow->nshc4;
  2231. + nsh->pad2 = 0;
  2232. + nsh->encap_eth_src = flow->encap_eth_src;
  2233. + nsh->encap_eth_dst = flow->encap_eth_dst;
  2234. + nsh->encap_eth_type = flow->encap_eth_type;
  2235. + nsh->pad1 = 0;
  2236. +}
  2237. +
  2238. static void
  2239. odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
  2240. bool export_mask, struct ofpbuf *buf)
  2241. {
  2242. struct ovs_key_ethernet *eth_key;
  2243. + struct ovs_key_nsh *nsh_key;
  2244. size_t encap;
  2245. const struct flow *flow = parms->flow;
  2246. const struct flow *data = export_mask ? parms->mask : parms->flow;
  2247. @@ -4403,6 +4579,12 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
  2248. nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, data->in_port.odp_port);
  2249. }
  2250. + if (flow->nsh_mdtype) {
  2251. + nsh_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_NSH,
  2252. + sizeof *nsh_key);
  2253. + get_nsh_key(data, nsh_key);
  2254. + }
  2255. +
  2256. eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ETHERNET,
  2257. sizeof *eth_key);
  2258. get_ethernet_key(data, eth_key);
  2259. @@ -5256,6 +5438,15 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
  2260. flow->in_port.odp_port = ODPP_NONE;
  2261. }
  2262. + /* NSH header. */
  2263. + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_NSH)) {
  2264. + const struct ovs_key_nsh *nsh_key;
  2265. +
  2266. + nsh_key = nl_attr_get(attrs[OVS_KEY_ATTR_NSH]);
  2267. + put_nsh_key(nsh_key, flow);
  2268. + expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_NSH;
  2269. + }
  2270. +
  2271. /* Ethernet header. */
  2272. if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ETHERNET)) {
  2273. const struct ovs_key_ethernet *eth_key;
  2274. @@ -5557,6 +5748,29 @@ put_ethernet_key(const struct ovs_key_ethernet *eth, struct flow *flow)
  2275. flow->dl_dst = eth->eth_dst;
  2276. }
  2277. +void
  2278. +put_nsh_key(const struct ovs_key_nsh *nsh, struct flow *flow)
  2279. +{
  2280. + flow->nsh_mdtype = nsh->nsh_mdtype;
  2281. + flow->nsh_np = nsh->nsh_np;
  2282. + flow->nsi = nsh->nsi;
  2283. + flow->nsp = nsh->nsp;
  2284. + flow->nshc1 = nsh->nshc1;
  2285. + flow->nshc2 = nsh->nshc2;
  2286. + flow->nshc3 = nsh->nshc3;
  2287. + flow->nshc4 = nsh->nshc4;
  2288. + flow->encap_eth_src = nsh->encap_eth_src;
  2289. + flow->encap_eth_dst = nsh->encap_eth_dst;
  2290. + flow->encap_eth_type = nsh->encap_eth_type;
  2291. +}
  2292. +
  2293. +void
  2294. +flow_zero_nsh(struct flow *flow)
  2295. +{
  2296. + void *dst_p = &(flow->encap_eth_dst);
  2297. + memset(dst_p, 0, 40);
  2298. +}
  2299. +
  2300. static void
  2301. commit_set_ether_addr_action(const struct flow *flow, struct flow *base_flow,
  2302. struct ofpbuf *odp_actions,
  2303. @@ -5608,6 +5822,64 @@ commit_vlan_action(ovs_be16 vlan_tci, struct flow *base,
  2304. base->vlan_tci = vlan_tci;
  2305. }
  2306. +static void
  2307. +commit_nsh_pop_action(const struct ovs_key_nsh *flow_key,
  2308. + const struct ovs_key_nsh *base_key,
  2309. + struct ofpbuf *odp_actions, struct flow_wildcards *wc)
  2310. +{
  2311. +
  2312. + if (memcmp(flow_key, base_key, sizeof (struct ovs_key_nsh))) {
  2313. + memset(&wc->masks.nsh_mdtype, 0xff, sizeof wc->masks.nsh_mdtype);
  2314. +
  2315. + if (base_key->nsh_mdtype) {
  2316. + nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_NSH);
  2317. + }
  2318. + }
  2319. +}
  2320. +
  2321. +static void
  2322. +commit_nsh_push_action(const struct ovs_key_nsh *flow_key,
  2323. + const struct ovs_key_nsh *base_key,
  2324. + struct ofpbuf *odp_actions)
  2325. +{
  2326. + if (memcmp(flow_key, base_key, sizeof (struct ovs_key_nsh))) {
  2327. + if (flow_key->nsh_mdtype) {
  2328. + struct ovs_action_push_nsh nsh;
  2329. + nsh.nsh_mdtype = flow_key->nsh_mdtype;
  2330. + struct eth_nsh_hdr *eth_nsh_header = (struct eth_nsh_hdr *)nsh.header;
  2331. + memset(eth_nsh_header, 0, sizeof *eth_nsh_header);
  2332. + eth_nsh_header->nsh_hdr.base.length = 6;
  2333. + eth_nsh_header->nsh_hdr.base.proto = flow_key->nsh_np;
  2334. + eth_nsh_header->nsh_hdr.base.mdtype = flow_key->nsh_mdtype;
  2335. + eth_nsh_header->nsh_hdr.base.proto = flow_key->nsh_np;
  2336. + eth_nsh_header->nsh_hdr.base.path_hdr = flow_key->nsp >> 8 | flow_key->nsi << 24;
  2337. + eth_nsh_header->nsh_hdr.ctx.nshc1 = flow_key->nshc1;
  2338. + eth_nsh_header->nsh_hdr.ctx.nshc2 = flow_key->nshc2;
  2339. + eth_nsh_header->nsh_hdr.ctx.nshc3 = flow_key->nshc3;
  2340. + eth_nsh_header->nsh_hdr.ctx.nshc4 = flow_key->nshc4;
  2341. +
  2342. + eth_nsh_header->encap_eth_header.encap_eth_type = htons(ETH_P_NSH);
  2343. + eth_nsh_header->encap_eth_header.encap_eth_dst = flow_key->encap_eth_dst;
  2344. + eth_nsh_header->encap_eth_header.encap_eth_src = flow_key->encap_eth_src;
  2345. +
  2346. + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_NSH,
  2347. + &nsh, sizeof nsh);
  2348. + }
  2349. + }
  2350. +}
  2351. +
  2352. +static void
  2353. +commit_nsh_action(const struct flow *flow, struct flow *base,
  2354. + struct ofpbuf *odp_actions, struct flow_wildcards *wc)
  2355. +{
  2356. + struct ovs_key_nsh flow_key, base_key;
  2357. + get_nsh_key(flow, &flow_key);
  2358. + get_nsh_key(base, &base_key);
  2359. + commit_nsh_pop_action(&flow_key, &base_key, odp_actions, wc);
  2360. + commit_nsh_push_action(&flow_key, &base_key, odp_actions);
  2361. +}
  2362. +
  2363. +
  2364. /* Wildcarding already done at action translation time. */
  2365. static void
  2366. commit_mpls_action(const struct flow *flow, struct flow *base,
  2367. @@ -6039,6 +6311,7 @@ commit_odp_actions(const struct flow *flow, struct flow *base,
  2368. slow2 = commit_set_icmp_action(flow, base, odp_actions, wc);
  2369. commit_mpls_action(flow, base, odp_actions);
  2370. commit_vlan_action(flow->vlan_tci, base, odp_actions, wc);
  2371. + commit_nsh_action(flow, base, odp_actions, wc);
  2372. commit_set_priority_action(flow, base, odp_actions, wc, use_masked);
  2373. commit_set_pkt_mark_action(flow, base, odp_actions, wc, use_masked);
  2374. diff --git a/lib/odp-util.h b/lib/odp-util.h
  2375. index a41bc76..c701482 100644
  2376. --- a/lib/odp-util.h
  2377. +++ b/lib/odp-util.h
  2378. @@ -66,7 +66,7 @@ enum slow_path_reason {
  2379. /* Mask of all slow_path_reasons. */
  2380. enum {
  2381. SLOW_PATH_REASON_MASK = 0
  2382. -#define SPR(ENUM, STRING, EXPLANATION) | 1 << ENUM##_INDEX
  2383. +#define SPR(ENUM, STRING, EXPLANATION) | 1 << ENUM##_INDEX
  2384. SLOW_PATH_REASONS
  2385. #undef SPR
  2386. };
  2387. @@ -126,6 +126,7 @@ void odp_portno_names_destroy(struct hmap *portno_names);
  2388. * OVS_KEY_ATTR_CT_ZONE 2 2 4 8
  2389. * OVS_KEY_ATTR_CT_MARK 4 -- 4 8
  2390. * OVS_KEY_ATTR_CT_LABEL 16 -- 4 20
  2391. + * OVS_KEY_ATTR_NSH 40 -- 4 44
  2392. * OVS_KEY_ATTR_ETHERNET 12 -- 4 16
  2393. * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype)
  2394. * OVS_KEY_ATTR_VLAN 2 2 4 8
  2395. @@ -150,6 +151,9 @@ struct odputil_keybuf {
  2396. uint32_t keybuf[DIV_ROUND_UP(ODPUTIL_FLOW_KEY_BYTES, 4)];
  2397. };
  2398. +void put_nsh_key(const struct ovs_key_nsh *, struct flow *);
  2399. +void get_nsh_key(const struct flow *flow, struct ovs_key_nsh *nsh);
  2400. +void flow_zero_nsh(struct flow *);
  2401. enum odp_key_fitness odp_tun_key_from_attr(const struct nlattr *, bool udpif,
  2402. struct flow_tnl *);
  2403. diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
  2404. index 15dbdec..2935ca6 100644
  2405. --- a/lib/ofp-actions.c
  2406. +++ b/lib/ofp-actions.c
  2407. @@ -304,6 +304,12 @@ enum ofp_raw_action_type {
  2408. /* NX1.0+(39): struct nx_action_output_trunc. */
  2409. NXAST_RAW_OUTPUT_TRUNC,
  2410. + /* NX1.0+(200): void. */
  2411. + NXAST_RAW_PUSH_NSH,
  2412. +
  2413. + /* NX1.0+(201): void. */
  2414. + NXAST_RAW_POP_NSH,
  2415. +
  2416. /* ## ------------------ ## */
  2417. /* ## Debugging actions. ## */
  2418. /* ## ------------------ ## */
  2419. @@ -394,6 +400,8 @@ ofpact_next_flattened(const struct ofpact *ofpact)
  2420. case OFPACT_SET_VLAN_PCP:
  2421. case OFPACT_STRIP_VLAN:
  2422. case OFPACT_PUSH_VLAN:
  2423. + case OFPACT_PUSH_NSH:
  2424. + case OFPACT_POP_NSH:
  2425. case OFPACT_SET_ETH_SRC:
  2426. case OFPACT_SET_ETH_DST:
  2427. case OFPACT_SET_IPV4_SRC:
  2428. @@ -1673,7 +1681,67 @@ format_PUSH_VLAN(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2429. ds_put_format(s, "%spush_vlan:%s%#"PRIx16,
  2430. colors.param, colors.end, ETH_TYPE_VLAN_8021Q);
  2431. }
  2432. -
  2433. +
  2434. +/* Push NSH header actions. */
  2435. +static enum ofperr
  2436. +decode_NXAST_RAW_PUSH_NSH(struct ofpbuf * out)
  2437. +{
  2438. + ofpact_put_PUSH_NSH(out)->ofpact.raw = NXAST_RAW_PUSH_NSH;
  2439. +
  2440. + return 0;
  2441. +}
  2442. +
  2443. +static void
  2444. +encode_PUSH_NSH(const struct ofpact_null *null OVS_UNUSED,
  2445. + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
  2446. +{
  2447. + put_NXAST_PUSH_NSH(out);
  2448. +}
  2449. +
  2450. +static char * OVS_WARN_UNUSED_RESULT
  2451. +parse_PUSH_NSH(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
  2452. + enum ofputil_protocol *usable_protocols OVS_UNUSED)
  2453. +{
  2454. + ofpact_put_PUSH_NSH(ofpacts)->ofpact.raw = NXAST_RAW_PUSH_NSH;;
  2455. + return NULL;
  2456. +}
  2457. +
  2458. +static void
  2459. +format_PUSH_NSH(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2460. +{
  2461. + ds_put_format(s, "push_nsh");
  2462. +}
  2463. +
  2464. +/* Pop NSH header actions. */
  2465. +static enum ofperr
  2466. +decode_NXAST_RAW_POP_NSH(struct ofpbuf * out)
  2467. +{
  2468. + ofpact_put_POP_NSH(out)->ofpact.raw = NXAST_RAW_POP_NSH;
  2469. +
  2470. + return 0;
  2471. +}
  2472. +
  2473. +static void
  2474. +encode_POP_NSH(const struct ofpact_null *null OVS_UNUSED,
  2475. + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
  2476. +{
  2477. + put_NXAST_POP_NSH(out);
  2478. +}
  2479. +
  2480. +static char * OVS_WARN_UNUSED_RESULT
  2481. +parse_POP_NSH(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
  2482. + enum ofputil_protocol *usable_protocols OVS_UNUSED)
  2483. +{
  2484. + ofpact_put_POP_NSH(ofpacts)->ofpact.raw = NXAST_RAW_POP_NSH;
  2485. + return NULL;
  2486. +}
  2487. +
  2488. +static void
  2489. +format_POP_NSH(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
  2490. +{
  2491. + ds_put_format(s, "pop_nsh");
  2492. +}
  2493. +
  2494. /* Action structure for OFPAT10_SET_DL_SRC/DST and OFPAT11_SET_DL_SRC/DST. */
  2495. struct ofp_action_dl_addr {
  2496. ovs_be16 type; /* Type. */
  2497. @@ -6181,6 +6249,8 @@ ofpact_is_set_or_move_action(const struct ofpact *a)
  2498. case OFPACT_POP_QUEUE:
  2499. case OFPACT_PUSH_MPLS:
  2500. case OFPACT_PUSH_VLAN:
  2501. + case OFPACT_PUSH_NSH:
  2502. + case OFPACT_POP_NSH:
  2503. case OFPACT_RESUBMIT:
  2504. case OFPACT_SAMPLE:
  2505. case OFPACT_STACK_POP:
  2506. @@ -6209,6 +6279,8 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
  2507. case OFPACT_POP_MPLS:
  2508. case OFPACT_PUSH_MPLS:
  2509. case OFPACT_PUSH_VLAN:
  2510. + case OFPACT_PUSH_NSH:
  2511. + case OFPACT_POP_NSH:
  2512. case OFPACT_REG_MOVE:
  2513. case OFPACT_SET_FIELD:
  2514. case OFPACT_SET_ETH_DST:
  2515. @@ -6436,6 +6508,8 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
  2516. case OFPACT_SET_VLAN_PCP:
  2517. case OFPACT_STRIP_VLAN:
  2518. case OFPACT_PUSH_VLAN:
  2519. + case OFPACT_PUSH_NSH:
  2520. + case OFPACT_POP_NSH:
  2521. case OFPACT_SET_ETH_SRC:
  2522. case OFPACT_SET_ETH_DST:
  2523. case OFPACT_SET_IPV4_SRC:
  2524. @@ -6909,6 +6983,8 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,
  2525. flow->vlan_tci |= htons(VLAN_CFI);
  2526. return 0;
  2527. + case OFPACT_PUSH_NSH:
  2528. + case OFPACT_POP_NSH:
  2529. case OFPACT_SET_ETH_SRC:
  2530. case OFPACT_SET_ETH_DST:
  2531. return 0;
  2532. @@ -7548,6 +7624,8 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
  2533. case OFPACT_SET_VLAN_PCP:
  2534. case OFPACT_STRIP_VLAN:
  2535. case OFPACT_PUSH_VLAN:
  2536. + case OFPACT_PUSH_NSH:
  2537. + case OFPACT_POP_NSH:
  2538. case OFPACT_SET_ETH_SRC:
  2539. case OFPACT_SET_ETH_DST:
  2540. case OFPACT_SET_IPV4_SRC:
  2541. diff --git a/lib/packets.c b/lib/packets.c
  2542. index e4c29d5..59afd0c 100644
  2543. --- a/lib/packets.c
  2544. +++ b/lib/packets.c
  2545. @@ -245,6 +245,29 @@ set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)
  2546. }
  2547. }
  2548. +void
  2549. +push_nsh(struct dp_packet *packet, const void *nsh)
  2550. +{
  2551. + void *header;
  2552. + const struct ovs_action_push_nsh *push_nsh_hdr = (const struct ovs_action_push_nsh *)nsh;
  2553. + const uint8_t *pdata = push_nsh_hdr->header;
  2554. + /* Now only support MD type1 */
  2555. + if (push_nsh_hdr->nsh_mdtype != NSH_M_TYPE1)
  2556. + return;
  2557. + header = dp_packet_push_uninit(packet, ETH_NSH_TYPE1_HEADER_SIZE);
  2558. +
  2559. + memcpy(header, pdata, ETH_NSH_TYPE1_HEADER_SIZE);
  2560. +}
  2561. +
  2562. +void
  2563. +pop_nsh(struct dp_packet *packet)
  2564. +{
  2565. + if (ETH_NSH_TYPE1_HEADER_SIZE > dp_packet_size(packet)) {
  2566. + return;
  2567. + }
  2568. + dp_packet_reset_packet(packet, ETH_NSH_TYPE1_HEADER_SIZE);
  2569. +}
  2570. +
  2571. static bool is_mpls(struct dp_packet *packet)
  2572. {
  2573. return packet->l2_5_ofs != UINT16_MAX;
  2574. diff --git a/lib/packets.h b/lib/packets.h
  2575. index dcfcd04..9d97a8a 100644
  2576. --- a/lib/packets.h
  2577. +++ b/lib/packets.h
  2578. @@ -279,6 +279,9 @@ void compose_rarp(struct dp_packet *, const struct eth_addr);
  2579. void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci);
  2580. void eth_pop_vlan(struct dp_packet *);
  2581. +void push_nsh(struct dp_packet *packet, const void *nsh);
  2582. +void pop_nsh(struct dp_packet *packet);
  2583. +
  2584. const char *eth_from_hex(const char *hex, struct dp_packet **packetp);
  2585. void eth_format_masked(const struct eth_addr ea,
  2586. const struct eth_addr *mask, struct ds *s);
  2587. diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
  2588. index c3234ee..faf5c76 100644
  2589. --- a/ofproto/ofproto-dpif-sflow.c
  2590. +++ b/ofproto/ofproto-dpif-sflow.c
  2591. @@ -970,6 +970,7 @@ sflow_read_set_action(const struct nlattr *attr,
  2592. case OVS_KEY_ATTR_IN_PORT:
  2593. case OVS_KEY_ATTR_ETHERNET:
  2594. case OVS_KEY_ATTR_VLAN:
  2595. + case OVS_KEY_ATTR_NSH:
  2596. break;
  2597. case OVS_KEY_ATTR_MPLS: {
  2598. diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
  2599. index bffbf35..f673ced 100644
  2600. --- a/ofproto/ofproto-dpif-upcall.c
  2601. +++ b/ofproto/ofproto-dpif-upcall.c
  2602. @@ -39,6 +39,7 @@
  2603. #include "seq.h"
  2604. #include "unixctl.h"
  2605. #include "openvswitch/vlog.h"
  2606. +#include "odp-util.h"
  2607. #define MAX_QUEUE_LENGTH 512
  2608. #define UPCALL_MAX_BATCH 64
  2609. @@ -746,6 +747,8 @@ recv_upcalls(struct handler *handler)
  2610. struct upcall *upcall = &upcalls[n_upcalls];
  2611. struct flow *flow = &flows[n_upcalls];
  2612. unsigned int mru;
  2613. + struct ovs_key_nsh reserve_nsh;
  2614. + bool nsh_mdtype_flag, encap_eth_type_flag;
  2615. int error;
  2616. ofpbuf_use_stub(recv_buf, recv_stubs[n_upcalls],
  2617. @@ -792,8 +795,16 @@ recv_upcalls(struct handler *handler)
  2618. upcall->actions = dupcall->actions;
  2619. pkt_metadata_from_flow(&dupcall->packet.md, flow);
  2620. +
  2621. + nsh_mdtype_flag = !!(flow->nsh_mdtype);
  2622. + if(nsh_mdtype_flag)
  2623. + get_nsh_key(flow, &reserve_nsh);
  2624. +
  2625. flow_extract(&dupcall->packet, flow);
  2626. + if(nsh_mdtype_flag)
  2627. + put_nsh_key(&reserve_nsh, flow);
  2628. +
  2629. error = process_upcall(udpif, upcall,
  2630. &upcall->odp_actions, &upcall->wc);
  2631. if (error) {
  2632. diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
  2633. index a17047d..c1166de 100644
  2634. --- a/ofproto/ofproto-dpif-xlate.c
  2635. +++ b/ofproto/ofproto-dpif-xlate.c
  2636. @@ -4451,6 +4451,8 @@ freeze_unroll_actions(const struct ofpact *a, const struct ofpact *end,
  2637. case OFPACT_SET_VLAN_PCP:
  2638. case OFPACT_STRIP_VLAN:
  2639. case OFPACT_PUSH_VLAN:
  2640. + case OFPACT_PUSH_NSH:
  2641. + case OFPACT_POP_NSH:
  2642. case OFPACT_SET_ETH_SRC:
  2643. case OFPACT_SET_ETH_DST:
  2644. case OFPACT_SET_IPV4_SRC:
  2645. @@ -4834,6 +4836,17 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
  2646. }
  2647. break;
  2648. + case OFPACT_PUSH_NSH:
  2649. + memset(&wc->masks.nsh_mdtype, 0xff, sizeof wc->masks.nsh_mdtype);
  2650. + flow->encap_eth_dst = flow->dl_dst;
  2651. + flow->encap_eth_src = flow->dl_src;
  2652. + break;
  2653. +
  2654. + case OFPACT_POP_NSH:
  2655. + memset(&wc->masks.nsh_mdtype, 0xff, sizeof wc->masks.nsh_mdtype);
  2656. + flow_zero_nsh(flow);
  2657. + break;
  2658. +
  2659. case OFPACT_STRIP_VLAN:
  2660. memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
  2661. flow->vlan_tci = htons(0);
  2662. diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
  2663. index f1e1209..0e30e6e 100644
  2664. --- a/ofproto/ofproto-dpif.h
  2665. +++ b/ofproto/ofproto-dpif.h
  2666. @@ -96,7 +96,6 @@ struct dpif_backer_support {
  2667. /* Each member represents support for related OVS_KEY_ATTR_* fields. */
  2668. struct odp_support odp;
  2669. };
  2670. -
  2671. bool ofproto_dpif_get_enable_ufid(const struct dpif_backer *backer);
  2672. struct dpif_backer_support *ofproto_dpif_get_support(const struct ofproto_dpif *);
  2673. diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
  2674. index 9a69071..acaec82 100644
  2675. --- a/ofproto/tunnel.c
  2676. +++ b/ofproto/tunnel.c
  2677. @@ -701,6 +701,7 @@ tnl_port_build_header(const struct ofport_dpif *ofport,
  2678. tnl_port = tnl_find_ofport(ofport);
  2679. ovs_assert(tnl_port);
  2680. res = netdev_build_header(tnl_port->netdev, data, params);
  2681. + data->exts = 0;
  2682. fat_rwlock_unlock(&rwlock);
  2683. return res;
  2684. diff --git a/tests/ofproto.at b/tests/ofproto.at
  2685. index 7b7f02b..431181a 100644
  2686. --- a/tests/ofproto.at
  2687. +++ b/tests/ofproto.at
  2688. @@ -2192,7 +2192,7 @@ head_table () {
  2689. 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
  2690. 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
  2691. 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
  2692. -metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 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
  2693. +metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 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
  2694. matching:
  2695. dp_hash: arbitrary mask
  2696. recirc_id: exact match or wildcard
  2697. @@ -2348,6 +2348,16 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4
  2698. nd_target: arbitrary mask
  2699. nd_sll: arbitrary mask
  2700. nd_tll: arbitrary mask
  2701. + nsp: arbitrary mask
  2702. + nsi: arbitrary mask
  2703. + nshc1: arbitrary mask
  2704. + nshc2: arbitrary mask
  2705. + nshc3: arbitrary mask
  2706. + nshc4: arbitrary mask
  2707. + nsh_mdtype: arbitrary mask
  2708. + nsh_np: arbitrary mask
  2709. + encap_eth_src: arbitrary mask
  2710. + encap_eth_dst: arbitrary mask
  2711. ' $1
  2712. }
  2713. diff --git a/tests/tunnel.at b/tests/tunnel.at
  2714. index 477517e..eb429d3 100644
  2715. --- a/tests/tunnel.at
  2716. +++ b/tests/tunnel.at
  2717. @@ -532,6 +532,322 @@ AT_CHECK([tail -1 stdout], [0],
  2718. OVS_VSWITCHD_STOP
  2719. AT_CLEANUP
  2720. +AT_SETUP([tunnel - VXLAN-GPE and NSH - Encapsulation - kernel space])
  2721. +OVS_VSWITCHD_START([dnl
  2722. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2723. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2724. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2725. + options:exts=gpe])
  2726. +
  2727. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2728. +ADD_OF_PORTS([br0], [90])
  2729. +AT_DATA([flows.txt], [dnl
  2730. +in_port=90 actions=resubmit:1,resubmit:2
  2731. +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
  2732. +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
  2733. +])
  2734. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2735. +
  2736. +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
  2737. + br0 65534/100: (dummy)
  2738. + p1 1/1: (dummy)
  2739. + p2 2/4790: (vxlan: dst_port=4790, key=flow, remote_ip=1.1.1.1)
  2740. + p90 90/90: (dummy)
  2741. +])
  2742. +
  2743. +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])
  2744. +AT_CHECK([tail -1 stdout], [0],
  2745. + [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
  2746. +])
  2747. +
  2748. +OVS_VSWITCHD_STOP
  2749. +AT_CLEANUP
  2750. +
  2751. +AT_SETUP([tunnel - VXLAN-GPE and NSH - Decapsulation - kernel space])
  2752. +OVS_VSWITCHD_START([dnl
  2753. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2754. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2755. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2756. + options:exts=gpe])
  2757. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2758. +
  2759. +AT_DATA([flows.txt], [dnl
  2760. +priority=200,in_port=2,tun_gpe_np=4,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,actions=pop_nsh,output=1
  2761. +])
  2762. +
  2763. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2764. +
  2765. +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
  2766. + br0 65534/100: (dummy)
  2767. + p1 1/1: (dummy)
  2768. + p2 2/4790: (vxlan: dst_port=4790, key=flow, remote_ip=1.1.1.1)
  2769. +])
  2770. +
  2771. +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])
  2772. +AT_CHECK([tail -1 stdout], [0],
  2773. + [Datapath actions: pop_nsh,1
  2774. +])
  2775. +
  2776. +OVS_VSWITCHD_STOP
  2777. +AT_CLEANUP
  2778. +
  2779. +AT_SETUP([Eth and NSH - Encapsulation - kernel space])
  2780. +OVS_VSWITCHD_START([dnl
  2781. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2782. + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
  2783. +
  2784. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2785. +ADD_OF_PORTS([br0], [90])
  2786. +AT_DATA([flows.txt], [dnl
  2787. +in_port=90 actions=resubmit:1,resubmit:2
  2788. +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
  2789. +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
  2790. +])
  2791. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2792. +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])
  2793. +AT_CHECK([tail -1 stdout], [0],
  2794. +[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
  2795. +])
  2796. +
  2797. +OVS_VSWITCHD_STOP
  2798. +AT_CLEANUP
  2799. +
  2800. +AT_SETUP([Eth and NSH - Decapsulation - kernel space])
  2801. +OVS_VSWITCHD_START([dnl
  2802. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2803. + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
  2804. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2805. +
  2806. +AT_DATA([flows.txt], [dnl
  2807. +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
  2808. +])
  2809. +
  2810. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2811. +
  2812. +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])
  2813. +AT_CHECK([tail -1 stdout], [0],
  2814. + [Datapath actions: pop_eth,pop_nsh,1
  2815. +])
  2816. +
  2817. +OVS_VSWITCHD_STOP
  2818. +AT_CLEANUP
  2819. +
  2820. +AT_SETUP([VXLANGPE+NSH to Eth+NSH - kernel space])
  2821. +OVS_VSWITCHD_START([dnl
  2822. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2823. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2824. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2825. + options:exts=gpe])
  2826. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2827. +
  2828. +AT_DATA([flows.txt], [dnl
  2829. +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
  2830. +
  2831. +])
  2832. +
  2833. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2834. +
  2835. +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])
  2836. +AT_CHECK([tail -1 stdout], [0],
  2837. + [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
  2838. +])
  2839. +
  2840. +OVS_VSWITCHD_STOP
  2841. +AT_CLEANUP
  2842. +
  2843. +AT_SETUP([Eth+NSH to VXLANGPE+NSH - kernel space])
  2844. +OVS_VSWITCHD_START([dnl
  2845. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2846. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2847. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2848. + options:exts=gpe])
  2849. +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
  2850. +
  2851. +AT_DATA([flows.txt], [dnl
  2852. +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
  2853. +])
  2854. +
  2855. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2856. +
  2857. +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])
  2858. +AT_CHECK([tail -1 stdout], [0],
  2859. + [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
  2860. +])
  2861. +
  2862. +OVS_VSWITCHD_STOP
  2863. +AT_CLEANUP
  2864. +
  2865. +AT_SETUP([tunnel - VXLAN-GPE and NSH - Encapsulation - user space])
  2866. +OVS_VSWITCHD_START([dnl
  2867. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2868. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2869. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2870. + options:exts=gpe])
  2871. +
  2872. +ADD_OF_PORTS([br0], [90])
  2873. +
  2874. +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 2.2.2.22/24], [0], [OK
  2875. +])
  2876. +AT_CHECK([
  2877. +ovs-appctl ovs/route/add 1.1.1.1/24 br0
  2878. +ovs-appctl tnl/arp/set br0 1.1.1.1 00:11:11:11:11:11
  2879. +],[0],[stdout])
  2880. +
  2881. +AT_DATA([flows.txt], [dnl
  2882. +in_port=90 actions=resubmit:1,resubmit:2
  2883. +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
  2884. +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
  2885. +])
  2886. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2887. +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])
  2888. +AT_CHECK([tail -1 stdout], [0],
  2889. + [Datapath actions: push_nsh(encap_eth_src=00:00:00:00:00:00,encap_eth_dst=00:00:00:00:00:00,nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=287454020,nshc2=1432778632,nshc3=2578103244,nshc4=3723427584),1,push_nsh(encap_eth_src=00:00:00:00:00:00,encap_eth_dst=00:00:00:00:00:00,nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=287454020,nshc2=1432778632,nshc3=2578103244,nshc4=3723427584),tnl_push(tnl_port(4790),header(size=50,type=4,eth(dst=00:11:11:11:11:11,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=1.1.1.1,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlan(flags=0xc000004,vni=0x0)),out_port(100))
  2890. +])
  2891. +
  2892. +OVS_VSWITCHD_STOP
  2893. +AT_CLEANUP
  2894. +
  2895. +AT_SETUP([tunnel - VXLAN-GPE and NSH - Decapsulation - user space])
  2896. +OVS_VSWITCHD_START([dnl
  2897. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2898. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  2899. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  2900. + options:exts=gpe])
  2901. +
  2902. +AT_DATA([flows.txt], [dnl
  2903. +priority=200,in_port=2,tun_gpe_np=4,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,actions=pop_nsh,output=1
  2904. +priority=100,in_port=1,actions=local
  2905. +])
  2906. +
  2907. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2908. +
  2909. +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.1.2/24], [0], [OK
  2910. +])
  2911. +
  2912. +AT_CHECK([ovs-appctl ovs/route/add 1.1.1.1/24 br0], [0], [OK
  2913. +])
  2914. +
  2915. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.1.1,dst=1.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4790)'], [0], [stdout])
  2916. +AT_CHECK([tail -1 stdout], [0],
  2917. + [Datapath actions: tnl_pop(4790)
  2918. +])
  2919. +
  2920. +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])
  2921. +AT_CHECK([tail -1 stdout], [0],
  2922. + [Datapath actions: pop_nsh,1
  2923. +])
  2924. +
  2925. +OVS_VSWITCHD_STOP
  2926. +AT_CLEANUP
  2927. +
  2928. +AT_SETUP([Eth and NSH - Encapsulation - user space])
  2929. +OVS_VSWITCHD_START([dnl
  2930. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2931. + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
  2932. +
  2933. +ADD_OF_PORTS([br0], [90])
  2934. +AT_DATA([flows.txt], [dnl
  2935. +in_port=90 actions=resubmit:1,resubmit:2
  2936. +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:00:11:22:33:44:55->encap_eth_dst,set_field:00:66:77:88:99:aa->encap_eth_src,output:1
  2937. +])
  2938. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2939. +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])
  2940. +AT_CHECK([tail -1 stdout], [0],
  2941. +[Datapath actions: push_nsh(encap_eth_src=00:66:77:88:99:aa,encap_eth_dst=00:11:22:33:44:55,nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=287454020,nshc2=1432778632,nshc3=2578103244,nshc4=0),1
  2942. +])
  2943. +
  2944. +OVS_VSWITCHD_STOP
  2945. +AT_CLEANUP
  2946. +
  2947. +AT_SETUP([Eth and NSH - Decapsulation - user space])
  2948. +OVS_VSWITCHD_START([dnl
  2949. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2950. + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
  2951. +
  2952. +AT_DATA([flows.txt], [dnl
  2953. +priority=200,in_port=2,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa,actions=pop_nsh,output=1
  2954. +])
  2955. +
  2956. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2957. +
  2958. +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
  2959. + br0 65534/100: (dummy)
  2960. + p1 1/1: (dummy)
  2961. + p2 2/2: (dummy)
  2962. +])
  2963. +
  2964. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy ',in_port(2),nsh(encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa,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])
  2965. +AT_CHECK([tail -1 stdout], [0],
  2966. + [Datapath actions: pop_nsh,1
  2967. +])
  2968. +
  2969. +OVS_VSWITCHD_STOP
  2970. +AT_CLEANUP
  2971. +
  2972. +AT_SETUP([VXLANGPE+NSH to Eth+NSH - user space])
  2973. +OVS_VSWITCHD_START([dnl
  2974. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  2975. + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 \
  2976. + -- add-port br0 p3 -- set Interface p3 type=vxlan options:key=flow \
  2977. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=3 \
  2978. + options:exts=gpe])
  2979. +
  2980. +AT_DATA([flows.txt], [dnl
  2981. +priority=200,in_port=3,tun_gpe_np=4,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,actions=set_field:00:11:22:33:44:55->encap_eth_dst,set_field:00:66:77:88:99:aa->encap_eth_src,output:2
  2982. +priority=100,in_port=1,actions=local
  2983. +])
  2984. +
  2985. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  2986. +
  2987. +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.1.2/24], [0], [OK
  2988. +])
  2989. +
  2990. +AT_CHECK([ovs-appctl ovs/route/add 1.1.1.1/24 br0], [0], [OK
  2991. +])
  2992. +
  2993. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.1.1,dst=1.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4790)'], [0], [stdout])
  2994. +AT_CHECK([tail -1 stdout], [0],
  2995. + [Datapath actions: tnl_pop(4790)
  2996. +])
  2997. +
  2998. +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])
  2999. +AT_CHECK([tail -1 stdout], [0],
  3000. + [Datapath actions: pop_nsh,push_nsh(encap_eth_src=00:66:77:88:99:aa,encap_eth_dst=00:11:22:33:44:55,nsh_mdtype=1,nsh_np=3,nsp=1122867,nsi=1140850688,nshc1=1144201745,nshc2=2289526357,nshc3=3434850969,nshc4=16772829),2
  3001. +])
  3002. +
  3003. +OVS_VSWITCHD_STOP
  3004. +AT_CLEANUP
  3005. +
  3006. +AT_SETUP([Eth+NSH to VXLANGPE+NSH - user space])
  3007. +OVS_VSWITCHD_START([dnl
  3008. + add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \
  3009. + -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
  3010. + options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2 \
  3011. + options:exts=gpe])
  3012. +
  3013. +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.1.2/24], [0], [OK
  3014. +])
  3015. +AT_CHECK([
  3016. +ovs-appctl ovs/route/add 1.1.1.1/24 br0
  3017. +ovs-appctl tnl/arp/set br0 1.1.1.1 00:11:11:11:11:11
  3018. +],[0],[stdout])
  3019. +
  3020. +AT_DATA([flows.txt], [dnl
  3021. +priority=200,in_port=1,nsh_mdtype=1,nsh_np=3,nsi=0x44,nsp=0x112233,encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa,actions=set_field:0x4->tun_gpe_np,output=2
  3022. +])
  3023. +
  3024. +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
  3025. +
  3026. +
  3027. +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy ',in_port(1),nsh(encap_eth_dst=00:11:22:33:44:55,encap_eth_src=00:66:77:88:99:aa,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])
  3028. +
  3029. +AT_CHECK([tail -1 stdout], [0],
  3030. + [Datapath actions: tnl_push(tnl_port(4790),header(size=50,type=4,eth(dst=00:11:11:11:11:11,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.1.2,dst=1.1.1.1,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlan(flags=0xc000004,vni=0x0)),out_port(100))
  3031. +])
  3032. +
  3033. +OVS_VSWITCHD_STOP
  3034. +AT_CLEANUP
  3035. +
  3036. AT_SETUP([tunnel - Geneve metadata])
  3037. OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \
  3038. options:remote_ip=1.1.1.1 ofport_request=1 \
  3039. --
  3040. 2.1.0