print-openflow-1.0.c 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560
  1. /*
  2. * This module implements decoding of OpenFlow protocol version 1.0 (wire
  3. * protocol 0x01). The decoder implements terse (default), detailed (-v) and
  4. * full (-vv) output formats and, as much as each format implies, detects and
  5. * tries to work around sizing anomalies inside the messages. The decoder marks
  6. * up bogus values of selected message fields and decodes partially captured
  7. * messages up to the snapshot end. It is based on the specification below:
  8. *
  9. * [OF10] http://www.openflow.org/documents/openflow-spec-v1.0.0.pdf
  10. *
  11. * Most functions in this file take 3 arguments into account:
  12. * * cp -- the pointer to the first octet to decode
  13. * * len -- the length of the current structure as declared on the wire
  14. * * ep -- the pointer to the end of the captured frame
  15. * They return either the pointer to the next not-yet-decoded part of the frame
  16. * or the value of ep, which means the current frame processing is over as it
  17. * has been fully decoded or is invalid or truncated. This way it is possible
  18. * to chain and nest such functions uniformly to decode an OF1.0 message, which
  19. * consists of several layers of nested structures.
  20. *
  21. * Decoding of Ethernet frames nested in OFPT_PACKET_IN and OFPT_PACKET_OUT
  22. * messages is done only when the verbosity level set by command-line argument
  23. * is "-vvv" or higher. In that case the verbosity level is temporarily
  24. * decremented by 3 during the nested frame decoding. For example, running
  25. * tcpdump with "-vvvv" will do full decoding of OpenFlow and "-v" decoding of
  26. * the nested frames.
  27. *
  28. * Partial decoding of Big Switch Networks vendor extensions is done after the
  29. * oftest (OpenFlow Testing Framework) and Loxigen (library generator) source
  30. * code.
  31. *
  32. *
  33. * Copyright (c) 2013 The TCPDUMP project
  34. * All rights reserved.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. * 1. Redistributions of source code must retain the above copyright
  40. * notice, this list of conditions and the following disclaimer.
  41. * 2. Redistributions in binary form must reproduce the above copyright
  42. * notice, this list of conditions and the following disclaimer in the
  43. * documentation and/or other materials provided with the distribution.
  44. *
  45. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  46. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  47. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  48. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  49. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  50. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  51. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  52. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  53. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  54. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  55. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  56. * POSSIBILITY OF SUCH DAMAGE.
  57. */
  58. /* \summary: OpenFlow protocol version 1.0 printer */
  59. #ifdef HAVE_CONFIG_H
  60. #include "config.h"
  61. #endif
  62. #include <netdissect-stdinc.h>
  63. #include "netdissect.h"
  64. #include "extract.h"
  65. #include "addrtoname.h"
  66. #include "ether.h"
  67. #include "ethertype.h"
  68. #include "ipproto.h"
  69. #include "oui.h"
  70. #include "openflow.h"
  71. static const char tstr[] = " [|openflow]";
  72. #define OFPT_HELLO 0x00
  73. #define OFPT_ERROR 0x01
  74. #define OFPT_ECHO_REQUEST 0x02
  75. #define OFPT_ECHO_REPLY 0x03
  76. #define OFPT_VENDOR 0x04
  77. #define OFPT_FEATURES_REQUEST 0x05
  78. #define OFPT_FEATURES_REPLY 0x06
  79. #define OFPT_GET_CONFIG_REQUEST 0x07
  80. #define OFPT_GET_CONFIG_REPLY 0x08
  81. #define OFPT_SET_CONFIG 0x09
  82. #define OFPT_PACKET_IN 0x0a
  83. #define OFPT_FLOW_REMOVED 0x0b
  84. #define OFPT_PORT_STATUS 0x0c
  85. #define OFPT_PACKET_OUT 0x0d
  86. #define OFPT_FLOW_MOD 0x0e
  87. #define OFPT_PORT_MOD 0x0f
  88. #define OFPT_STATS_REQUEST 0x10
  89. #define OFPT_STATS_REPLY 0x11
  90. #define OFPT_BARRIER_REQUEST 0x12
  91. #define OFPT_BARRIER_REPLY 0x13
  92. #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14
  93. #define OFPT_QUEUE_GET_CONFIG_REPLY 0x15
  94. static const struct tok ofpt_str[] = {
  95. { OFPT_HELLO, "HELLO" },
  96. { OFPT_ERROR, "ERROR" },
  97. { OFPT_ECHO_REQUEST, "ECHO_REQUEST" },
  98. { OFPT_ECHO_REPLY, "ECHO_REPLY" },
  99. { OFPT_VENDOR, "VENDOR" },
  100. { OFPT_FEATURES_REQUEST, "FEATURES_REQUEST" },
  101. { OFPT_FEATURES_REPLY, "FEATURES_REPLY" },
  102. { OFPT_GET_CONFIG_REQUEST, "GET_CONFIG_REQUEST" },
  103. { OFPT_GET_CONFIG_REPLY, "GET_CONFIG_REPLY" },
  104. { OFPT_SET_CONFIG, "SET_CONFIG" },
  105. { OFPT_PACKET_IN, "PACKET_IN" },
  106. { OFPT_FLOW_REMOVED, "FLOW_REMOVED" },
  107. { OFPT_PORT_STATUS, "PORT_STATUS" },
  108. { OFPT_PACKET_OUT, "PACKET_OUT" },
  109. { OFPT_FLOW_MOD, "FLOW_MOD" },
  110. { OFPT_PORT_MOD, "PORT_MOD" },
  111. { OFPT_STATS_REQUEST, "STATS_REQUEST" },
  112. { OFPT_STATS_REPLY, "STATS_REPLY" },
  113. { OFPT_BARRIER_REQUEST, "BARRIER_REQUEST" },
  114. { OFPT_BARRIER_REPLY, "BARRIER_REPLY" },
  115. { OFPT_QUEUE_GET_CONFIG_REQUEST, "QUEUE_GET_CONFIG_REQUEST" },
  116. { OFPT_QUEUE_GET_CONFIG_REPLY, "QUEUE_GET_CONFIG_REPLY" },
  117. { 0, NULL }
  118. };
  119. #define OFPPC_PORT_DOWN (1 << 0)
  120. #define OFPPC_NO_STP (1 << 1)
  121. #define OFPPC_NO_RECV (1 << 2)
  122. #define OFPPC_NO_RECV_STP (1 << 3)
  123. #define OFPPC_NO_FLOOD (1 << 4)
  124. #define OFPPC_NO_FWD (1 << 5)
  125. #define OFPPC_NO_PACKET_IN (1 << 6)
  126. static const struct tok ofppc_bm[] = {
  127. { OFPPC_PORT_DOWN, "PORT_DOWN" },
  128. { OFPPC_NO_STP, "NO_STP" },
  129. { OFPPC_NO_RECV, "NO_RECV" },
  130. { OFPPC_NO_RECV_STP, "NO_RECV_STP" },
  131. { OFPPC_NO_FLOOD, "NO_FLOOD" },
  132. { OFPPC_NO_FWD, "NO_FWD" },
  133. { OFPPC_NO_PACKET_IN, "NO_PACKET_IN" },
  134. { 0, NULL }
  135. };
  136. #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \
  137. OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
  138. OFPPC_NO_PACKET_IN))
  139. #define OFPPS_LINK_DOWN (1 << 0)
  140. #define OFPPS_STP_LISTEN (0 << 8)
  141. #define OFPPS_STP_LEARN (1 << 8)
  142. #define OFPPS_STP_FORWARD (2 << 8)
  143. #define OFPPS_STP_BLOCK (3 << 8)
  144. #define OFPPS_STP_MASK (3 << 8)
  145. static const struct tok ofpps_bm[] = {
  146. { OFPPS_LINK_DOWN, "LINK_DOWN" },
  147. { OFPPS_STP_LISTEN, "STP_LISTEN" },
  148. { OFPPS_STP_LEARN, "STP_LEARN" },
  149. { OFPPS_STP_FORWARD, "STP_FORWARD" },
  150. { OFPPS_STP_BLOCK, "STP_BLOCK" },
  151. { 0, NULL }
  152. };
  153. #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \
  154. OFPPS_STP_FORWARD | OFPPS_STP_BLOCK))
  155. #define OFPP_MAX 0xff00
  156. #define OFPP_IN_PORT 0xfff8
  157. #define OFPP_TABLE 0xfff9
  158. #define OFPP_NORMAL 0xfffa
  159. #define OFPP_FLOOD 0xfffb
  160. #define OFPP_ALL 0xfffc
  161. #define OFPP_CONTROLLER 0xfffd
  162. #define OFPP_LOCAL 0xfffe
  163. #define OFPP_NONE 0xffff
  164. static const struct tok ofpp_str[] = {
  165. { OFPP_MAX, "MAX" },
  166. { OFPP_IN_PORT, "IN_PORT" },
  167. { OFPP_TABLE, "TABLE" },
  168. { OFPP_NORMAL, "NORMAL" },
  169. { OFPP_FLOOD, "FLOOD" },
  170. { OFPP_ALL, "ALL" },
  171. { OFPP_CONTROLLER, "CONTROLLER" },
  172. { OFPP_LOCAL, "LOCAL" },
  173. { OFPP_NONE, "NONE" },
  174. { 0, NULL }
  175. };
  176. #define OFPPF_10MB_HD (1 << 0)
  177. #define OFPPF_10MB_FD (1 << 1)
  178. #define OFPPF_100MB_HD (1 << 2)
  179. #define OFPPF_100MB_FD (1 << 3)
  180. #define OFPPF_1GB_HD (1 << 4)
  181. #define OFPPF_1GB_FD (1 << 5)
  182. #define OFPPF_10GB_FD (1 << 6)
  183. #define OFPPF_COPPER (1 << 7)
  184. #define OFPPF_FIBER (1 << 8)
  185. #define OFPPF_AUTONEG (1 << 9)
  186. #define OFPPF_PAUSE (1 << 10)
  187. #define OFPPF_PAUSE_ASYM (1 << 11)
  188. static const struct tok ofppf_bm[] = {
  189. { OFPPF_10MB_HD, "10MB_HD" },
  190. { OFPPF_10MB_FD, "10MB_FD" },
  191. { OFPPF_100MB_HD, "100MB_HD" },
  192. { OFPPF_100MB_FD, "100MB_FD" },
  193. { OFPPF_1GB_HD, "1GB_HD" },
  194. { OFPPF_1GB_FD, "1GB_FD" },
  195. { OFPPF_10GB_FD, "10GB_FD" },
  196. { OFPPF_COPPER, "COPPER" },
  197. { OFPPF_FIBER, "FIBER" },
  198. { OFPPF_AUTONEG, "AUTONEG" },
  199. { OFPPF_PAUSE, "PAUSE" },
  200. { OFPPF_PAUSE_ASYM, "PAUSE_ASYM" },
  201. { 0, NULL }
  202. };
  203. #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
  204. OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
  205. OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \
  206. OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
  207. #define OFPQT_NONE 0x0000
  208. #define OFPQT_MIN_RATE 0x0001
  209. static const struct tok ofpqt_str[] = {
  210. { OFPQT_NONE, "NONE" },
  211. { OFPQT_MIN_RATE, "MIN_RATE" },
  212. { 0, NULL }
  213. };
  214. #define OFPFW_IN_PORT (1 << 0)
  215. #define OFPFW_DL_VLAN (1 << 1)
  216. #define OFPFW_DL_SRC (1 << 2)
  217. #define OFPFW_DL_DST (1 << 3)
  218. #define OFPFW_DL_TYPE (1 << 4)
  219. #define OFPFW_NW_PROTO (1 << 5)
  220. #define OFPFW_TP_SRC (1 << 6)
  221. #define OFPFW_TP_DST (1 << 7)
  222. #define OFPFW_NW_SRC_SHIFT 8
  223. #define OFPFW_NW_SRC_BITS 6
  224. #define OFPFW_NW_SRC_MASK (((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT)
  225. #define OFPFW_NW_DST_SHIFT 14
  226. #define OFPFW_NW_DST_BITS 6
  227. #define OFPFW_NW_DST_MASK (((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT)
  228. #define OFPFW_DL_VLAN_PCP (1 << 20)
  229. #define OFPFW_NW_TOS (1 << 21)
  230. #define OFPFW_ALL ((1 << 22) - 1)
  231. static const struct tok ofpfw_bm[] = {
  232. { OFPFW_IN_PORT, "IN_PORT" },
  233. { OFPFW_DL_VLAN, "DL_VLAN" },
  234. { OFPFW_DL_SRC, "DL_SRC" },
  235. { OFPFW_DL_DST, "DL_DST" },
  236. { OFPFW_DL_TYPE, "DL_TYPE" },
  237. { OFPFW_NW_PROTO, "NW_PROTO" },
  238. { OFPFW_TP_SRC, "TP_SRC" },
  239. { OFPFW_TP_DST, "TP_DST" },
  240. { OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" },
  241. { OFPFW_NW_TOS, "NW_TOS" },
  242. { 0, NULL }
  243. };
  244. /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19
  245. * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding
  246. * other than that of tok2str(). The macro below includes these bits such that
  247. * they are not reported as bogus in the decoding. */
  248. #define OFPFW_U (~(OFPFW_ALL))
  249. #define OFPAT_OUTPUT 0x0000
  250. #define OFPAT_SET_VLAN_VID 0x0001
  251. #define OFPAT_SET_VLAN_PCP 0x0002
  252. #define OFPAT_STRIP_VLAN 0x0003
  253. #define OFPAT_SET_DL_SRC 0x0004
  254. #define OFPAT_SET_DL_DST 0x0005
  255. #define OFPAT_SET_NW_SRC 0x0006
  256. #define OFPAT_SET_NW_DST 0x0007
  257. #define OFPAT_SET_NW_TOS 0x0008
  258. #define OFPAT_SET_TP_SRC 0x0009
  259. #define OFPAT_SET_TP_DST 0x000a
  260. #define OFPAT_ENQUEUE 0x000b
  261. #define OFPAT_VENDOR 0xffff
  262. static const struct tok ofpat_str[] = {
  263. { OFPAT_OUTPUT, "OUTPUT" },
  264. { OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
  265. { OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
  266. { OFPAT_STRIP_VLAN, "STRIP_VLAN" },
  267. { OFPAT_SET_DL_SRC, "SET_DL_SRC" },
  268. { OFPAT_SET_DL_DST, "SET_DL_DST" },
  269. { OFPAT_SET_NW_SRC, "SET_NW_SRC" },
  270. { OFPAT_SET_NW_DST, "SET_NW_DST" },
  271. { OFPAT_SET_NW_TOS, "SET_NW_TOS" },
  272. { OFPAT_SET_TP_SRC, "SET_TP_SRC" },
  273. { OFPAT_SET_TP_DST, "SET_TP_DST" },
  274. { OFPAT_ENQUEUE, "ENQUEUE" },
  275. { OFPAT_VENDOR, "VENDOR" },
  276. { 0, NULL }
  277. };
  278. /* bit-shifted, w/o vendor action */
  279. static const struct tok ofpat_bm[] = {
  280. { 1 << OFPAT_OUTPUT, "OUTPUT" },
  281. { 1 << OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
  282. { 1 << OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
  283. { 1 << OFPAT_STRIP_VLAN, "STRIP_VLAN" },
  284. { 1 << OFPAT_SET_DL_SRC, "SET_DL_SRC" },
  285. { 1 << OFPAT_SET_DL_DST, "SET_DL_DST" },
  286. { 1 << OFPAT_SET_NW_SRC, "SET_NW_SRC" },
  287. { 1 << OFPAT_SET_NW_DST, "SET_NW_DST" },
  288. { 1 << OFPAT_SET_NW_TOS, "SET_NW_TOS" },
  289. { 1 << OFPAT_SET_TP_SRC, "SET_TP_SRC" },
  290. { 1 << OFPAT_SET_TP_DST, "SET_TP_DST" },
  291. { 1 << OFPAT_ENQUEUE, "ENQUEUE" },
  292. { 0, NULL }
  293. };
  294. #define OFPAT_U (~(1 << OFPAT_OUTPUT | 1 << OFPAT_SET_VLAN_VID | \
  295. 1 << OFPAT_SET_VLAN_PCP | 1 << OFPAT_STRIP_VLAN | \
  296. 1 << OFPAT_SET_DL_SRC | 1 << OFPAT_SET_DL_DST | \
  297. 1 << OFPAT_SET_NW_SRC | 1 << OFPAT_SET_NW_DST | \
  298. 1 << OFPAT_SET_NW_TOS | 1 << OFPAT_SET_TP_SRC | \
  299. 1 << OFPAT_SET_TP_DST | 1 << OFPAT_ENQUEUE))
  300. #define OFPC_FLOW_STATS (1 << 0)
  301. #define OFPC_TABLE_STATS (1 << 1)
  302. #define OFPC_PORT_STATS (1 << 2)
  303. #define OFPC_STP (1 << 3)
  304. #define OFPC_RESERVED (1 << 4)
  305. #define OFPC_IP_REASM (1 << 5)
  306. #define OFPC_QUEUE_STATS (1 << 6)
  307. #define OFPC_ARP_MATCH_IP (1 << 7)
  308. static const struct tok ofp_capabilities_bm[] = {
  309. { OFPC_FLOW_STATS, "FLOW_STATS" },
  310. { OFPC_TABLE_STATS, "TABLE_STATS" },
  311. { OFPC_PORT_STATS, "PORT_STATS" },
  312. { OFPC_STP, "STP" },
  313. { OFPC_RESERVED, "RESERVED" }, /* not in the mask below */
  314. { OFPC_IP_REASM, "IP_REASM" },
  315. { OFPC_QUEUE_STATS, "QUEUE_STATS" },
  316. { OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" },
  317. { 0, NULL }
  318. };
  319. #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
  320. OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
  321. OFPC_ARP_MATCH_IP))
  322. #define OFPC_FRAG_NORMAL 0x0000
  323. #define OFPC_FRAG_DROP 0x0001
  324. #define OFPC_FRAG_REASM 0x0002
  325. #define OFPC_FRAG_MASK 0x0003
  326. static const struct tok ofp_config_str[] = {
  327. { OFPC_FRAG_NORMAL, "FRAG_NORMAL" },
  328. { OFPC_FRAG_DROP, "FRAG_DROP" },
  329. { OFPC_FRAG_REASM, "FRAG_REASM" },
  330. { 0, NULL }
  331. };
  332. #define OFPFC_ADD 0x0000
  333. #define OFPFC_MODIFY 0x0001
  334. #define OFPFC_MODIFY_STRICT 0x0002
  335. #define OFPFC_DELETE 0x0003
  336. #define OFPFC_DELETE_STRICT 0x0004
  337. static const struct tok ofpfc_str[] = {
  338. { OFPFC_ADD, "ADD" },
  339. { OFPFC_MODIFY, "MODIFY" },
  340. { OFPFC_MODIFY_STRICT, "MODIFY_STRICT" },
  341. { OFPFC_DELETE, "DELETE" },
  342. { OFPFC_DELETE_STRICT, "DELETE_STRICT" },
  343. { 0, NULL }
  344. };
  345. static const struct tok bufferid_str[] = {
  346. { 0xffffffff, "NONE" },
  347. { 0, NULL }
  348. };
  349. #define OFPFF_SEND_FLOW_REM (1 << 0)
  350. #define OFPFF_CHECK_OVERLAP (1 << 1)
  351. #define OFPFF_EMERG (1 << 2)
  352. static const struct tok ofpff_bm[] = {
  353. { OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" },
  354. { OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" },
  355. { OFPFF_EMERG, "EMERG" },
  356. { 0, NULL }
  357. };
  358. #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG))
  359. #define OFPST_DESC 0x0000
  360. #define OFPST_FLOW 0x0001
  361. #define OFPST_AGGREGATE 0x0002
  362. #define OFPST_TABLE 0x0003
  363. #define OFPST_PORT 0x0004
  364. #define OFPST_QUEUE 0x0005
  365. #define OFPST_VENDOR 0xffff
  366. static const struct tok ofpst_str[] = {
  367. { OFPST_DESC, "DESC" },
  368. { OFPST_FLOW, "FLOW" },
  369. { OFPST_AGGREGATE, "AGGREGATE" },
  370. { OFPST_TABLE, "TABLE" },
  371. { OFPST_PORT, "PORT" },
  372. { OFPST_QUEUE, "QUEUE" },
  373. { OFPST_VENDOR, "VENDOR" },
  374. { 0, NULL }
  375. };
  376. static const struct tok tableid_str[] = {
  377. { 0xfe, "EMERG" },
  378. { 0xff, "ALL" },
  379. { 0, NULL }
  380. };
  381. #define OFPQ_ALL 0xffffffff
  382. static const struct tok ofpq_str[] = {
  383. { OFPQ_ALL, "ALL" },
  384. { 0, NULL }
  385. };
  386. #define OFPSF_REPLY_MORE 0x0001
  387. static const struct tok ofpsf_reply_bm[] = {
  388. { OFPSF_REPLY_MORE, "MORE" },
  389. { 0, NULL }
  390. };
  391. #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE))
  392. #define OFPR_NO_MATCH 0x00
  393. #define OFPR_ACTION 0x01
  394. static const struct tok ofpr_str[] = {
  395. { OFPR_NO_MATCH, "NO_MATCH" },
  396. { OFPR_ACTION, "ACTION" },
  397. { 0, NULL }
  398. };
  399. #define OFPRR_IDLE_TIMEOUT 0x00
  400. #define OFPRR_HARD_TIMEOUT 0x01
  401. #define OFPRR_DELETE 0x02
  402. static const struct tok ofprr_str[] = {
  403. { OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" },
  404. { OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" },
  405. { OFPRR_DELETE, "DELETE" },
  406. { 0, NULL }
  407. };
  408. #define OFPPR_ADD 0x00
  409. #define OFPPR_DELETE 0x01
  410. #define OFPPR_MODIFY 0x02
  411. static const struct tok ofppr_str[] = {
  412. { OFPPR_ADD, "ADD" },
  413. { OFPPR_DELETE, "DELETE" },
  414. { OFPPR_MODIFY, "MODIFY" },
  415. { 0, NULL }
  416. };
  417. #define OFPET_HELLO_FAILED 0x0000
  418. #define OFPET_BAD_REQUEST 0x0001
  419. #define OFPET_BAD_ACTION 0x0002
  420. #define OFPET_FLOW_MOD_FAILED 0x0003
  421. #define OFPET_PORT_MOD_FAILED 0x0004
  422. #define OFPET_QUEUE_OP_FAILED 0x0005
  423. static const struct tok ofpet_str[] = {
  424. { OFPET_HELLO_FAILED, "HELLO_FAILED" },
  425. { OFPET_BAD_REQUEST, "BAD_REQUEST" },
  426. { OFPET_BAD_ACTION, "BAD_ACTION" },
  427. { OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" },
  428. { OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" },
  429. { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
  430. { 0, NULL }
  431. };
  432. #define OFPHFC_INCOMPATIBLE 0x0000
  433. #define OFPHFC_EPERM 0x0001
  434. static const struct tok ofphfc_str[] = {
  435. { OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" },
  436. { OFPHFC_EPERM, "EPERM" },
  437. { 0, NULL }
  438. };
  439. #define OFPBRC_BAD_VERSION 0x0000
  440. #define OFPBRC_BAD_TYPE 0x0001
  441. #define OFPBRC_BAD_STAT 0x0002
  442. #define OFPBRC_BAD_VENDOR 0x0003
  443. #define OFPBRC_BAD_SUBTYPE 0x0004
  444. #define OFPBRC_EPERM 0x0005
  445. #define OFPBRC_BAD_LEN 0x0006
  446. #define OFPBRC_BUFFER_EMPTY 0x0007
  447. #define OFPBRC_BUFFER_UNKNOWN 0x0008
  448. static const struct tok ofpbrc_str[] = {
  449. { OFPBRC_BAD_VERSION, "BAD_VERSION" },
  450. { OFPBRC_BAD_TYPE, "BAD_TYPE" },
  451. { OFPBRC_BAD_STAT, "BAD_STAT" },
  452. { OFPBRC_BAD_VENDOR, "BAD_VENDOR" },
  453. { OFPBRC_BAD_SUBTYPE, "BAD_SUBTYPE" },
  454. { OFPBRC_EPERM, "EPERM" },
  455. { OFPBRC_BAD_LEN, "BAD_LEN" },
  456. { OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" },
  457. { OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" },
  458. { 0, NULL }
  459. };
  460. #define OFPBAC_BAD_TYPE 0x0000
  461. #define OFPBAC_BAD_LEN 0x0001
  462. #define OFPBAC_BAD_VENDOR 0x0002
  463. #define OFPBAC_BAD_VENDOR_TYPE 0x0003
  464. #define OFPBAC_BAD_OUT_PORT 0x0004
  465. #define OFPBAC_BAD_ARGUMENT 0x0005
  466. #define OFPBAC_EPERM 0x0006
  467. #define OFPBAC_TOO_MANY 0x0007
  468. #define OFPBAC_BAD_QUEUE 0x0008
  469. static const struct tok ofpbac_str[] = {
  470. { OFPBAC_BAD_TYPE, "BAD_TYPE" },
  471. { OFPBAC_BAD_LEN, "BAD_LEN" },
  472. { OFPBAC_BAD_VENDOR, "BAD_VENDOR" },
  473. { OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" },
  474. { OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" },
  475. { OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" },
  476. { OFPBAC_EPERM, "EPERM" },
  477. { OFPBAC_TOO_MANY, "TOO_MANY" },
  478. { OFPBAC_BAD_QUEUE, "BAD_QUEUE" },
  479. { 0, NULL }
  480. };
  481. #define OFPFMFC_ALL_TABLES_FULL 0x0000
  482. #define OFPFMFC_OVERLAP 0x0001
  483. #define OFPFMFC_EPERM 0x0002
  484. #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003
  485. #define OFPFMFC_BAD_COMMAND 0x0004
  486. #define OFPFMFC_UNSUPPORTED 0x0005
  487. static const struct tok ofpfmfc_str[] = {
  488. { OFPFMFC_ALL_TABLES_FULL, "ALL_TABLES_FULL" },
  489. { OFPFMFC_OVERLAP, "OVERLAP" },
  490. { OFPFMFC_EPERM, "EPERM" },
  491. { OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" },
  492. { OFPFMFC_BAD_COMMAND, "BAD_COMMAND" },
  493. { OFPFMFC_UNSUPPORTED, "UNSUPPORTED" },
  494. { 0, NULL }
  495. };
  496. #define OFPPMFC_BAD_PORT 0x0000
  497. #define OFPPMFC_BAD_HW_ADDR 0x0001
  498. static const struct tok ofppmfc_str[] = {
  499. { OFPPMFC_BAD_PORT, "BAD_PORT" },
  500. { OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" },
  501. { 0, NULL }
  502. };
  503. #define OFPQOFC_BAD_PORT 0x0000
  504. #define OFPQOFC_BAD_QUEUE 0x0001
  505. #define OFPQOFC_EPERM 0x0002
  506. static const struct tok ofpqofc_str[] = {
  507. { OFPQOFC_BAD_PORT, "BAD_PORT" },
  508. { OFPQOFC_BAD_QUEUE, "BAD_QUEUE" },
  509. { OFPQOFC_EPERM, "EPERM" },
  510. { 0, NULL }
  511. };
  512. static const struct tok empty_str[] = {
  513. { 0, NULL }
  514. };
  515. /* lengths (fixed or minimal) of particular protocol structures */
  516. #define OF_SWITCH_CONFIG_LEN 12
  517. #define OF_PHY_PORT_LEN 48
  518. #define OF_SWITCH_FEATURES_LEN 32
  519. #define OF_PORT_STATUS_LEN 64
  520. #define OF_PORT_MOD_LEN 32
  521. #define OF_PACKET_IN_LEN 20
  522. #define OF_ACTION_OUTPUT_LEN 8
  523. #define OF_ACTION_VLAN_VID_LEN 8
  524. #define OF_ACTION_VLAN_PCP_LEN 8
  525. #define OF_ACTION_DL_ADDR_LEN 16
  526. #define OF_ACTION_NW_ADDR_LEN 8
  527. #define OF_ACTION_TP_PORT_LEN 8
  528. #define OF_ACTION_NW_TOS_LEN 8
  529. #define OF_ACTION_VENDOR_HEADER_LEN 8
  530. #define OF_ACTION_HEADER_LEN 8
  531. #define OF_PACKET_OUT_LEN 16
  532. #define OF_MATCH_LEN 40
  533. #define OF_FLOW_MOD_LEN 72
  534. #define OF_FLOW_REMOVED_LEN 88
  535. #define OF_ERROR_MSG_LEN 12
  536. #define OF_STATS_REQUEST_LEN 12
  537. #define OF_STATS_REPLY_LEN 12
  538. #define OF_DESC_STATS_LEN 1056
  539. #define OF_FLOW_STATS_REQUEST_LEN 44
  540. #define OF_FLOW_STATS_LEN 88
  541. #define OF_AGGREGATE_STATS_REQUEST_LEN 44
  542. #define OF_AGGREGATE_STATS_REPLY_LEN 24
  543. #define OF_TABLE_STATS_LEN 64
  544. #define OF_PORT_STATS_REQUEST_LEN 8
  545. #define OF_PORT_STATS_LEN 104
  546. #define OF_VENDOR_HEADER_LEN 12
  547. #define OF_QUEUE_PROP_HEADER_LEN 8
  548. #define OF_QUEUE_PROP_MIN_RATE_LEN 16
  549. #define OF_PACKET_QUEUE_LEN 8
  550. #define OF_QUEUE_GET_CONFIG_REQUEST_LEN 12
  551. #define OF_QUEUE_GET_CONFIG_REPLY_LEN 16
  552. #define OF_ACTION_ENQUEUE_LEN 16
  553. #define OF_QUEUE_STATS_REQUEST_LEN 8
  554. #define OF_QUEUE_STATS_LEN 32
  555. /* miscellaneous constants from [OF10] */
  556. #define OFP_MAX_TABLE_NAME_LEN 32
  557. #define OFP_MAX_PORT_NAME_LEN 16
  558. #define DESC_STR_LEN 256
  559. #define SERIAL_NUM_LEN 32
  560. #define OFP_VLAN_NONE 0xffff
  561. /* vendor extensions */
  562. #define BSN_SET_IP_MASK 0
  563. #define BSN_GET_IP_MASK_REQUEST 1
  564. #define BSN_GET_IP_MASK_REPLY 2
  565. #define BSN_SET_MIRRORING 3
  566. #define BSN_GET_MIRRORING_REQUEST 4
  567. #define BSN_GET_MIRRORING_REPLY 5
  568. #define BSN_SHELL_COMMAND 6
  569. #define BSN_SHELL_OUTPUT 7
  570. #define BSN_SHELL_STATUS 8
  571. #define BSN_GET_INTERFACES_REQUEST 9
  572. #define BSN_GET_INTERFACES_REPLY 10
  573. #define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11
  574. #define BSN_SET_L2_TABLE_REQUEST 12
  575. #define BSN_GET_L2_TABLE_REQUEST 13
  576. #define BSN_GET_L2_TABLE_REPLY 14
  577. #define BSN_VIRTUAL_PORT_CREATE_REQUEST 15
  578. #define BSN_VIRTUAL_PORT_CREATE_REPLY 16
  579. #define BSN_VIRTUAL_PORT_REMOVE_REQUEST 17
  580. #define BSN_BW_ENABLE_SET_REQUEST 18
  581. #define BSN_BW_ENABLE_GET_REQUEST 19
  582. #define BSN_BW_ENABLE_GET_REPLY 20
  583. #define BSN_BW_CLEAR_DATA_REQUEST 21
  584. #define BSN_BW_CLEAR_DATA_REPLY 22
  585. #define BSN_BW_ENABLE_SET_REPLY 23
  586. #define BSN_SET_L2_TABLE_REPLY 24
  587. #define BSN_SET_PKTIN_SUPPRESSION_REPLY 25
  588. #define BSN_VIRTUAL_PORT_REMOVE_REPLY 26
  589. #define BSN_HYBRID_GET_REQUEST 27
  590. #define BSN_HYBRID_GET_REPLY 28
  591. /* 29 */
  592. /* 30 */
  593. #define BSN_PDU_TX_REQUEST 31
  594. #define BSN_PDU_TX_REPLY 32
  595. #define BSN_PDU_RX_REQUEST 33
  596. #define BSN_PDU_RX_REPLY 34
  597. #define BSN_PDU_RX_TIMEOUT 35
  598. static const struct tok bsn_subtype_str[] = {
  599. { BSN_SET_IP_MASK, "SET_IP_MASK" },
  600. { BSN_GET_IP_MASK_REQUEST, "GET_IP_MASK_REQUEST" },
  601. { BSN_GET_IP_MASK_REPLY, "GET_IP_MASK_REPLY" },
  602. { BSN_SET_MIRRORING, "SET_MIRRORING" },
  603. { BSN_GET_MIRRORING_REQUEST, "GET_MIRRORING_REQUEST" },
  604. { BSN_GET_MIRRORING_REPLY, "GET_MIRRORING_REPLY" },
  605. { BSN_SHELL_COMMAND, "SHELL_COMMAND" },
  606. { BSN_SHELL_OUTPUT, "SHELL_OUTPUT" },
  607. { BSN_SHELL_STATUS, "SHELL_STATUS" },
  608. { BSN_GET_INTERFACES_REQUEST, "GET_INTERFACES_REQUEST" },
  609. { BSN_GET_INTERFACES_REPLY, "GET_INTERFACES_REPLY" },
  610. { BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" },
  611. { BSN_SET_L2_TABLE_REQUEST, "SET_L2_TABLE_REQUEST" },
  612. { BSN_GET_L2_TABLE_REQUEST, "GET_L2_TABLE_REQUEST" },
  613. { BSN_GET_L2_TABLE_REPLY, "GET_L2_TABLE_REPLY" },
  614. { BSN_VIRTUAL_PORT_CREATE_REQUEST, "VIRTUAL_PORT_CREATE_REQUEST" },
  615. { BSN_VIRTUAL_PORT_CREATE_REPLY, "VIRTUAL_PORT_CREATE_REPLY" },
  616. { BSN_VIRTUAL_PORT_REMOVE_REQUEST, "VIRTUAL_PORT_REMOVE_REQUEST" },
  617. { BSN_BW_ENABLE_SET_REQUEST, "BW_ENABLE_SET_REQUEST" },
  618. { BSN_BW_ENABLE_GET_REQUEST, "BW_ENABLE_GET_REQUEST" },
  619. { BSN_BW_ENABLE_GET_REPLY, "BW_ENABLE_GET_REPLY" },
  620. { BSN_BW_CLEAR_DATA_REQUEST, "BW_CLEAR_DATA_REQUEST" },
  621. { BSN_BW_CLEAR_DATA_REPLY, "BW_CLEAR_DATA_REPLY" },
  622. { BSN_BW_ENABLE_SET_REPLY, "BW_ENABLE_SET_REPLY" },
  623. { BSN_SET_L2_TABLE_REPLY, "SET_L2_TABLE_REPLY" },
  624. { BSN_SET_PKTIN_SUPPRESSION_REPLY, "SET_PKTIN_SUPPRESSION_REPLY" },
  625. { BSN_VIRTUAL_PORT_REMOVE_REPLY, "VIRTUAL_PORT_REMOVE_REPLY" },
  626. { BSN_HYBRID_GET_REQUEST, "HYBRID_GET_REQUEST" },
  627. { BSN_HYBRID_GET_REPLY, "HYBRID_GET_REPLY" },
  628. { BSN_PDU_TX_REQUEST, "PDU_TX_REQUEST" },
  629. { BSN_PDU_TX_REPLY, "PDU_TX_REPLY" },
  630. { BSN_PDU_RX_REQUEST, "PDU_RX_REQUEST" },
  631. { BSN_PDU_RX_REPLY, "PDU_RX_REPLY" },
  632. { BSN_PDU_RX_TIMEOUT, "PDU_RX_TIMEOUT" },
  633. { 0, NULL }
  634. };
  635. #define BSN_ACTION_MIRROR 1
  636. #define BSN_ACTION_SET_TUNNEL_DST 2
  637. /* 3 */
  638. #define BSN_ACTION_CHECKSUM 4
  639. static const struct tok bsn_action_subtype_str[] = {
  640. { BSN_ACTION_MIRROR, "MIRROR" },
  641. { BSN_ACTION_SET_TUNNEL_DST, "SET_TUNNEL_DST" },
  642. { BSN_ACTION_CHECKSUM, "CHECKSUM" },
  643. { 0, NULL }
  644. };
  645. static const struct tok bsn_mirror_copy_stage_str[] = {
  646. { 0, "INGRESS" },
  647. { 1, "EGRESS" },
  648. { 0, NULL },
  649. };
  650. static const struct tok bsn_onoff_str[] = {
  651. { 0, "OFF" },
  652. { 1, "ON" },
  653. { 0, NULL },
  654. };
  655. static const char *
  656. vlan_str(const uint16_t vid)
  657. {
  658. static char buf[sizeof("65535 (bogus)")];
  659. const char *fmt;
  660. if (vid == OFP_VLAN_NONE)
  661. return "NONE";
  662. fmt = (vid > 0 && vid < 0x0fff) ? "%u" : "%u (bogus)";
  663. snprintf(buf, sizeof(buf), fmt, vid);
  664. return buf;
  665. }
  666. static const char *
  667. pcp_str(const uint8_t pcp)
  668. {
  669. static char buf[sizeof("255 (bogus)")];
  670. snprintf(buf, sizeof(buf), pcp <= 7 ? "%u" : "%u (bogus)", pcp);
  671. return buf;
  672. }
  673. static void
  674. of10_bitmap_print(netdissect_options *ndo,
  675. const struct tok *t, const uint32_t v, const uint32_t u)
  676. {
  677. const char *sep = " (";
  678. if (v == 0)
  679. return;
  680. /* assigned bits */
  681. for (; t->s != NULL; t++)
  682. if (v & t->v) {
  683. ND_PRINT((ndo, "%s%s", sep, t->s));
  684. sep = ", ";
  685. }
  686. /* unassigned bits? */
  687. ND_PRINT((ndo, v & u ? ") (bogus)" : ")"));
  688. }
  689. static const u_char *
  690. of10_data_print(netdissect_options *ndo,
  691. const u_char *cp, const u_char *ep, const u_int len)
  692. {
  693. if (len == 0)
  694. return cp;
  695. /* data */
  696. ND_PRINT((ndo, "\n\t data (%u octets)", len));
  697. ND_TCHECK2(*cp, len);
  698. if (ndo->ndo_vflag >= 2)
  699. hex_and_ascii_print(ndo, "\n\t ", cp, len);
  700. return cp + len;
  701. trunc:
  702. ND_PRINT((ndo, "%s", tstr));
  703. return ep;
  704. }
  705. static const u_char *
  706. of10_bsn_message_print(netdissect_options *ndo,
  707. const u_char *cp, const u_char *ep, const u_int len)
  708. {
  709. const u_char *cp0 = cp;
  710. uint32_t subtype;
  711. if (len < 4)
  712. goto invalid;
  713. /* subtype */
  714. ND_TCHECK2(*cp, 4);
  715. subtype = EXTRACT_32BITS(cp);
  716. cp += 4;
  717. ND_PRINT((ndo, "\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype)));
  718. switch (subtype) {
  719. case BSN_GET_IP_MASK_REQUEST:
  720. /*
  721. * 0 1 2 3
  722. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  723. * +---------------+---------------+---------------+---------------+
  724. * | subtype |
  725. * +---------------+---------------+---------------+---------------+
  726. * | index | pad |
  727. * +---------------+---------------+---------------+---------------+
  728. * | pad |
  729. * +---------------+---------------+---------------+---------------+
  730. *
  731. */
  732. if (len != 12)
  733. goto invalid;
  734. /* index */
  735. ND_TCHECK2(*cp, 1);
  736. ND_PRINT((ndo, ", index %u", *cp));
  737. cp += 1;
  738. /* pad */
  739. ND_TCHECK2(*cp, 7);
  740. cp += 7;
  741. break;
  742. case BSN_SET_IP_MASK:
  743. case BSN_GET_IP_MASK_REPLY:
  744. /*
  745. * 0 1 2 3
  746. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  747. * +---------------+---------------+---------------+---------------+
  748. * | subtype |
  749. * +---------------+---------------+---------------+---------------+
  750. * | index | pad |
  751. * +---------------+---------------+---------------+---------------+
  752. * | mask |
  753. * +---------------+---------------+---------------+---------------+
  754. *
  755. */
  756. if (len != 12)
  757. goto invalid;
  758. /* index */
  759. ND_TCHECK2(*cp, 1);
  760. ND_PRINT((ndo, ", index %u", *cp));
  761. cp += 1;
  762. /* pad */
  763. ND_TCHECK2(*cp, 3);
  764. cp += 3;
  765. /* mask */
  766. ND_TCHECK2(*cp, 4);
  767. ND_PRINT((ndo, ", mask %s", ipaddr_string(ndo, cp)));
  768. cp += 4;
  769. break;
  770. case BSN_SET_MIRRORING:
  771. case BSN_GET_MIRRORING_REQUEST:
  772. case BSN_GET_MIRRORING_REPLY:
  773. /*
  774. * 0 1 2 3
  775. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  776. * +---------------+---------------+---------------+---------------+
  777. * | subtype |
  778. * +---------------+---------------+---------------+---------------+
  779. * | report m. p. | pad |
  780. * +---------------+---------------+---------------+---------------+
  781. *
  782. */
  783. if (len != 8)
  784. goto invalid;
  785. /* report_mirror_ports */
  786. ND_TCHECK2(*cp, 1);
  787. ND_PRINT((ndo, ", report_mirror_ports %s", tok2str(bsn_onoff_str, "bogus (%u)", *cp)));
  788. cp += 1;
  789. /* pad */
  790. ND_TCHECK2(*cp, 3);
  791. cp += 3;
  792. break;
  793. case BSN_GET_INTERFACES_REQUEST:
  794. case BSN_GET_L2_TABLE_REQUEST:
  795. case BSN_BW_ENABLE_GET_REQUEST:
  796. case BSN_BW_CLEAR_DATA_REQUEST:
  797. case BSN_HYBRID_GET_REQUEST:
  798. /*
  799. * 0 1 2 3
  800. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  801. * +---------------+---------------+---------------+---------------+
  802. * | subtype |
  803. * +---------------+---------------+---------------+---------------+
  804. *
  805. */
  806. if (len != 4)
  807. goto invalid;
  808. break;
  809. case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
  810. /*
  811. * 0 1 2 3
  812. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  813. * +---------------+---------------+---------------+---------------+
  814. * | subtype |
  815. * +---------------+---------------+---------------+---------------+
  816. * | vport_no |
  817. * +---------------+---------------+---------------+---------------+
  818. *
  819. */
  820. if (len != 8)
  821. goto invalid;
  822. /* vport_no */
  823. ND_TCHECK2(*cp, 4);
  824. ND_PRINT((ndo, ", vport_no %u", EXTRACT_32BITS(cp)));
  825. cp += 4;
  826. break;
  827. case BSN_SHELL_COMMAND:
  828. /*
  829. * 0 1 2 3
  830. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  831. * +---------------+---------------+---------------+---------------+
  832. * | subtype |
  833. * +---------------+---------------+---------------+---------------+
  834. * | service |
  835. * +---------------+---------------+---------------+---------------+
  836. * | data ...
  837. * +---------------+---------------+--------
  838. *
  839. */
  840. if (len < 8)
  841. goto invalid;
  842. /* service */
  843. ND_TCHECK2(*cp, 4);
  844. ND_PRINT((ndo, ", service %u", EXTRACT_32BITS(cp)));
  845. cp += 4;
  846. /* data */
  847. ND_PRINT((ndo, ", data '"));
  848. if (fn_printn(ndo, cp, len - 8, ep)) {
  849. ND_PRINT((ndo, "'"));
  850. goto trunc;
  851. }
  852. ND_PRINT((ndo, "'"));
  853. cp += len - 8;
  854. break;
  855. case BSN_SHELL_OUTPUT:
  856. /*
  857. * 0 1 2 3
  858. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  859. * +---------------+---------------+---------------+---------------+
  860. * | subtype |
  861. * +---------------+---------------+---------------+---------------+
  862. * | data ...
  863. * +---------------+---------------+--------
  864. *
  865. */
  866. /* already checked that len >= 4 */
  867. /* data */
  868. ND_PRINT((ndo, ", data '"));
  869. if (fn_printn(ndo, cp, len - 4, ep)) {
  870. ND_PRINT((ndo, "'"));
  871. goto trunc;
  872. }
  873. ND_PRINT((ndo, "'"));
  874. cp += len - 4;
  875. break;
  876. case BSN_SHELL_STATUS:
  877. /*
  878. * 0 1 2 3
  879. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  880. * +---------------+---------------+---------------+---------------+
  881. * | subtype |
  882. * +---------------+---------------+---------------+---------------+
  883. * | status |
  884. * +---------------+---------------+---------------+---------------+
  885. *
  886. */
  887. if (len != 8)
  888. goto invalid;
  889. /* status */
  890. ND_TCHECK2(*cp, 4);
  891. ND_PRINT((ndo, ", status 0x%08x", EXTRACT_32BITS(cp)));
  892. cp += 4;
  893. break;
  894. default:
  895. ND_TCHECK2(*cp, len - 4);
  896. cp += len - 4;
  897. }
  898. return cp;
  899. invalid: /* skip the undersized data */
  900. ND_PRINT((ndo, "%s", istr));
  901. ND_TCHECK2(*cp0, len);
  902. return cp0 + len;
  903. trunc:
  904. ND_PRINT((ndo, "%s", tstr));
  905. return ep;
  906. }
  907. static const u_char *
  908. of10_bsn_actions_print(netdissect_options *ndo,
  909. const u_char *cp, const u_char *ep, const u_int len)
  910. {
  911. const u_char *cp0 = cp;
  912. uint32_t subtype, vlan_tag;
  913. if (len < 4)
  914. goto invalid;
  915. /* subtype */
  916. ND_TCHECK2(*cp, 4);
  917. subtype = EXTRACT_32BITS(cp);
  918. cp += 4;
  919. ND_PRINT((ndo, "\n\t subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype)));
  920. switch (subtype) {
  921. case BSN_ACTION_MIRROR:
  922. /*
  923. * 0 1 2 3
  924. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  925. * +---------------+---------------+---------------+---------------+
  926. * | subtype |
  927. * +---------------+---------------+---------------+---------------+
  928. * | dest_port |
  929. * +---------------+---------------+---------------+---------------+
  930. * | vlan_tag |
  931. * +---------------+---------------+---------------+---------------+
  932. * | copy_stage | pad |
  933. * +---------------+---------------+---------------+---------------+
  934. *
  935. */
  936. if (len != 16)
  937. goto invalid;
  938. /* dest_port */
  939. ND_TCHECK2(*cp, 4);
  940. ND_PRINT((ndo, ", dest_port %u", EXTRACT_32BITS(cp)));
  941. cp += 4;
  942. /* vlan_tag */
  943. ND_TCHECK2(*cp, 4);
  944. vlan_tag = EXTRACT_32BITS(cp);
  945. cp += 4;
  946. switch (vlan_tag >> 16) {
  947. case 0:
  948. ND_PRINT((ndo, ", vlan_tag none"));
  949. break;
  950. case ETHERTYPE_8021Q:
  951. ND_PRINT((ndo, ", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff)));
  952. break;
  953. default:
  954. ND_PRINT((ndo, ", vlan_tag unknown (0x%04x)", vlan_tag >> 16));
  955. }
  956. /* copy_stage */
  957. ND_TCHECK2(*cp, 1);
  958. ND_PRINT((ndo, ", copy_stage %s", tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", *cp)));
  959. cp += 1;
  960. /* pad */
  961. ND_TCHECK2(*cp, 3);
  962. cp += 3;
  963. break;
  964. default:
  965. ND_TCHECK2(*cp, len - 4);
  966. cp += len - 4;
  967. }
  968. return cp;
  969. invalid:
  970. ND_PRINT((ndo, "%s", istr));
  971. ND_TCHECK2(*cp0, len);
  972. return cp0 + len;
  973. trunc:
  974. ND_PRINT((ndo, "%s", tstr));
  975. return ep;
  976. }
  977. static const u_char *
  978. of10_vendor_action_print(netdissect_options *ndo,
  979. const u_char *cp, const u_char *ep, const u_int len)
  980. {
  981. uint32_t vendor;
  982. const u_char *(*decoder)(netdissect_options *, const u_char *, const u_char *, const u_int);
  983. if (len < 4)
  984. goto invalid;
  985. /* vendor */
  986. ND_TCHECK2(*cp, 4);
  987. vendor = EXTRACT_32BITS(cp);
  988. cp += 4;
  989. ND_PRINT((ndo, ", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)));
  990. /* data */
  991. decoder =
  992. vendor == OUI_BSN ? of10_bsn_actions_print :
  993. of10_data_print;
  994. return decoder(ndo, cp, ep, len - 4);
  995. invalid: /* skip the undersized data */
  996. ND_PRINT((ndo, "%s", istr));
  997. ND_TCHECK2(*cp, len);
  998. return cp + len;
  999. trunc:
  1000. ND_PRINT((ndo, "%s", tstr));
  1001. return ep;
  1002. }
  1003. static const u_char *
  1004. of10_vendor_message_print(netdissect_options *ndo,
  1005. const u_char *cp, const u_char *ep, const u_int len)
  1006. {
  1007. uint32_t vendor;
  1008. const u_char *(*decoder)(netdissect_options *, const u_char *, const u_char *, u_int);
  1009. if (len < 4)
  1010. goto invalid;
  1011. /* vendor */
  1012. ND_TCHECK2(*cp, 4);
  1013. vendor = EXTRACT_32BITS(cp);
  1014. cp += 4;
  1015. ND_PRINT((ndo, ", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)));
  1016. /* data */
  1017. decoder =
  1018. vendor == OUI_BSN ? of10_bsn_message_print :
  1019. of10_data_print;
  1020. return decoder(ndo, cp, ep, len - 4);
  1021. invalid: /* skip the undersized data */
  1022. ND_PRINT((ndo, "%s", istr));
  1023. ND_TCHECK2(*cp, len);
  1024. return cp + len;
  1025. trunc:
  1026. ND_PRINT((ndo, "%s", tstr));
  1027. return ep;
  1028. }
  1029. /* Vendor ID is mandatory, data is optional. */
  1030. static const u_char *
  1031. of10_vendor_data_print(netdissect_options *ndo,
  1032. const u_char *cp, const u_char *ep, const u_int len)
  1033. {
  1034. uint32_t vendor;
  1035. if (len < 4)
  1036. goto invalid;
  1037. /* vendor */
  1038. ND_TCHECK2(*cp, 4);
  1039. vendor = EXTRACT_32BITS(cp);
  1040. cp += 4;
  1041. ND_PRINT((ndo, ", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)));
  1042. /* data */
  1043. return of10_data_print(ndo, cp, ep, len - 4);
  1044. invalid: /* skip the undersized data */
  1045. ND_PRINT((ndo, "%s", istr));
  1046. ND_TCHECK2(*cp, len);
  1047. return cp + len;
  1048. trunc:
  1049. ND_PRINT((ndo, "%s", tstr));
  1050. return ep;
  1051. }
  1052. static const u_char *
  1053. of10_packet_data_print(netdissect_options *ndo,
  1054. const u_char *cp, const u_char *ep, const u_int len)
  1055. {
  1056. if (len == 0)
  1057. return cp;
  1058. /* data */
  1059. ND_PRINT((ndo, "\n\t data (%u octets)", len));
  1060. if (ndo->ndo_vflag < 3)
  1061. return cp + len;
  1062. ND_TCHECK2(*cp, len);
  1063. ndo->ndo_vflag -= 3;
  1064. ND_PRINT((ndo, ", frame decoding below\n"));
  1065. ether_print(ndo, cp, len, ndo->ndo_snapend - cp, NULL, NULL);
  1066. ndo->ndo_vflag += 3;
  1067. return cp + len;
  1068. trunc:
  1069. ND_PRINT((ndo, "%s", tstr));
  1070. return ep;
  1071. }
  1072. /* [OF10] Section 5.2.1 */
  1073. static const u_char *
  1074. of10_phy_ports_print(netdissect_options *ndo,
  1075. const u_char *cp, const u_char *ep, u_int len)
  1076. {
  1077. const u_char *cp0 = cp;
  1078. const u_int len0 = len;
  1079. while (len) {
  1080. if (len < OF_PHY_PORT_LEN)
  1081. goto invalid;
  1082. /* port_no */
  1083. ND_TCHECK2(*cp, 2);
  1084. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1085. cp += 2;
  1086. /* hw_addr */
  1087. ND_TCHECK2(*cp, ETHER_ADDR_LEN);
  1088. ND_PRINT((ndo, ", hw_addr %s", etheraddr_string(ndo, cp)));
  1089. cp += ETHER_ADDR_LEN;
  1090. /* name */
  1091. ND_TCHECK2(*cp, OFP_MAX_PORT_NAME_LEN);
  1092. ND_PRINT((ndo, ", name '"));
  1093. fn_print(ndo, cp, cp + OFP_MAX_PORT_NAME_LEN);
  1094. ND_PRINT((ndo, "'"));
  1095. cp += OFP_MAX_PORT_NAME_LEN;
  1096. if (ndo->ndo_vflag < 2) {
  1097. ND_TCHECK2(*cp, 24);
  1098. cp += 24;
  1099. goto next_port;
  1100. }
  1101. /* config */
  1102. ND_TCHECK2(*cp, 4);
  1103. ND_PRINT((ndo, "\n\t config 0x%08x", EXTRACT_32BITS(cp)));
  1104. of10_bitmap_print(ndo, ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U);
  1105. cp += 4;
  1106. /* state */
  1107. ND_TCHECK2(*cp, 4);
  1108. ND_PRINT((ndo, "\n\t state 0x%08x", EXTRACT_32BITS(cp)));
  1109. of10_bitmap_print(ndo, ofpps_bm, EXTRACT_32BITS(cp), OFPPS_U);
  1110. cp += 4;
  1111. /* curr */
  1112. ND_TCHECK2(*cp, 4);
  1113. ND_PRINT((ndo, "\n\t curr 0x%08x", EXTRACT_32BITS(cp)));
  1114. of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U);
  1115. cp += 4;
  1116. /* advertised */
  1117. ND_TCHECK2(*cp, 4);
  1118. ND_PRINT((ndo, "\n\t advertised 0x%08x", EXTRACT_32BITS(cp)));
  1119. of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U);
  1120. cp += 4;
  1121. /* supported */
  1122. ND_TCHECK2(*cp, 4);
  1123. ND_PRINT((ndo, "\n\t supported 0x%08x", EXTRACT_32BITS(cp)));
  1124. of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U);
  1125. cp += 4;
  1126. /* peer */
  1127. ND_TCHECK2(*cp, 4);
  1128. ND_PRINT((ndo, "\n\t peer 0x%08x", EXTRACT_32BITS(cp)));
  1129. of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U);
  1130. cp += 4;
  1131. next_port:
  1132. len -= OF_PHY_PORT_LEN;
  1133. } /* while */
  1134. return cp;
  1135. invalid: /* skip the undersized trailing data */
  1136. ND_PRINT((ndo, "%s", istr));
  1137. ND_TCHECK2(*cp0, len0);
  1138. return cp0 + len0;
  1139. trunc:
  1140. ND_PRINT((ndo, "%s", tstr));
  1141. return ep;
  1142. }
  1143. /* [OF10] Section 5.2.2 */
  1144. static const u_char *
  1145. of10_queue_props_print(netdissect_options *ndo,
  1146. const u_char *cp, const u_char *ep, u_int len)
  1147. {
  1148. const u_char *cp0 = cp;
  1149. const u_int len0 = len;
  1150. uint16_t property, plen, rate;
  1151. while (len) {
  1152. u_char plen_bogus = 0, skip = 0;
  1153. if (len < OF_QUEUE_PROP_HEADER_LEN)
  1154. goto invalid;
  1155. /* property */
  1156. ND_TCHECK2(*cp, 2);
  1157. property = EXTRACT_16BITS(cp);
  1158. cp += 2;
  1159. ND_PRINT((ndo, "\n\t property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property)));
  1160. /* len */
  1161. ND_TCHECK2(*cp, 2);
  1162. plen = EXTRACT_16BITS(cp);
  1163. cp += 2;
  1164. ND_PRINT((ndo, ", len %u", plen));
  1165. if (plen < OF_QUEUE_PROP_HEADER_LEN || plen > len)
  1166. goto invalid;
  1167. /* pad */
  1168. ND_TCHECK2(*cp, 4);
  1169. cp += 4;
  1170. /* property-specific constraints and decoding */
  1171. switch (property) {
  1172. case OFPQT_NONE:
  1173. plen_bogus = plen != OF_QUEUE_PROP_HEADER_LEN;
  1174. break;
  1175. case OFPQT_MIN_RATE:
  1176. plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_LEN;
  1177. break;
  1178. default:
  1179. skip = 1;
  1180. }
  1181. if (plen_bogus) {
  1182. ND_PRINT((ndo, " (bogus)"));
  1183. skip = 1;
  1184. }
  1185. if (skip) {
  1186. ND_TCHECK2(*cp, plen - 4);
  1187. cp += plen - 4;
  1188. goto next_property;
  1189. }
  1190. if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */
  1191. /* rate */
  1192. ND_TCHECK2(*cp, 2);
  1193. rate = EXTRACT_16BITS(cp);
  1194. cp += 2;
  1195. if (rate > 1000)
  1196. ND_PRINT((ndo, ", rate disabled"));
  1197. else
  1198. ND_PRINT((ndo, ", rate %u.%u%%", rate / 10, rate % 10));
  1199. /* pad */
  1200. ND_TCHECK2(*cp, 6);
  1201. cp += 6;
  1202. }
  1203. next_property:
  1204. len -= plen;
  1205. } /* while */
  1206. return cp;
  1207. invalid: /* skip the rest of queue properties */
  1208. ND_PRINT((ndo, "%s", istr));
  1209. ND_TCHECK2(*cp0, len0);
  1210. return cp0 + len0;
  1211. trunc:
  1212. ND_PRINT((ndo, "%s", tstr));
  1213. return ep;
  1214. }
  1215. /* ibid */
  1216. static const u_char *
  1217. of10_queues_print(netdissect_options *ndo,
  1218. const u_char *cp, const u_char *ep, u_int len)
  1219. {
  1220. const u_char *cp0 = cp;
  1221. const u_int len0 = len;
  1222. uint16_t desclen;
  1223. while (len) {
  1224. if (len < OF_PACKET_QUEUE_LEN)
  1225. goto invalid;
  1226. /* queue_id */
  1227. ND_TCHECK2(*cp, 4);
  1228. ND_PRINT((ndo, "\n\t queue_id %u", EXTRACT_32BITS(cp)));
  1229. cp += 4;
  1230. /* len */
  1231. ND_TCHECK2(*cp, 2);
  1232. desclen = EXTRACT_16BITS(cp);
  1233. cp += 2;
  1234. ND_PRINT((ndo, ", len %u", desclen));
  1235. if (desclen < OF_PACKET_QUEUE_LEN || desclen > len)
  1236. goto invalid;
  1237. /* pad */
  1238. ND_TCHECK2(*cp, 2);
  1239. cp += 2;
  1240. /* properties */
  1241. if (ndo->ndo_vflag < 2) {
  1242. ND_TCHECK2(*cp, desclen - OF_PACKET_QUEUE_LEN);
  1243. cp += desclen - OF_PACKET_QUEUE_LEN;
  1244. goto next_queue;
  1245. }
  1246. if (ep == (cp = of10_queue_props_print(ndo, cp, ep, desclen - OF_PACKET_QUEUE_LEN)))
  1247. return ep; /* end of snapshot */
  1248. next_queue:
  1249. len -= desclen;
  1250. } /* while */
  1251. return cp;
  1252. invalid: /* skip the rest of queues */
  1253. ND_PRINT((ndo, "%s", istr));
  1254. ND_TCHECK2(*cp0, len0);
  1255. return cp0 + len0;
  1256. trunc:
  1257. ND_PRINT((ndo, "%s", tstr));
  1258. return ep;
  1259. }
  1260. /* [OF10] Section 5.2.3 */
  1261. static const u_char *
  1262. of10_match_print(netdissect_options *ndo,
  1263. const char *pfx, const u_char *cp, const u_char *ep)
  1264. {
  1265. uint32_t wildcards;
  1266. uint16_t dl_type;
  1267. uint8_t nw_proto;
  1268. u_char nw_bits;
  1269. const char *field_name;
  1270. /* wildcards */
  1271. ND_TCHECK2(*cp, 4);
  1272. wildcards = EXTRACT_32BITS(cp);
  1273. if (wildcards & OFPFW_U)
  1274. ND_PRINT((ndo, "%swildcards 0x%08x (bogus)", pfx, wildcards));
  1275. cp += 4;
  1276. /* in_port */
  1277. ND_TCHECK2(*cp, 2);
  1278. if (! (wildcards & OFPFW_IN_PORT))
  1279. ND_PRINT((ndo, "%smatch in_port %s", pfx, tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1280. cp += 2;
  1281. /* dl_src */
  1282. ND_TCHECK2(*cp, ETHER_ADDR_LEN);
  1283. if (! (wildcards & OFPFW_DL_SRC))
  1284. ND_PRINT((ndo, "%smatch dl_src %s", pfx, etheraddr_string(ndo, cp)));
  1285. cp += ETHER_ADDR_LEN;
  1286. /* dl_dst */
  1287. ND_TCHECK2(*cp, ETHER_ADDR_LEN);
  1288. if (! (wildcards & OFPFW_DL_DST))
  1289. ND_PRINT((ndo, "%smatch dl_dst %s", pfx, etheraddr_string(ndo, cp)));
  1290. cp += ETHER_ADDR_LEN;
  1291. /* dl_vlan */
  1292. ND_TCHECK2(*cp, 2);
  1293. if (! (wildcards & OFPFW_DL_VLAN))
  1294. ND_PRINT((ndo, "%smatch dl_vlan %s", pfx, vlan_str(EXTRACT_16BITS(cp))));
  1295. cp += 2;
  1296. /* dl_vlan_pcp */
  1297. ND_TCHECK2(*cp, 1);
  1298. if (! (wildcards & OFPFW_DL_VLAN_PCP))
  1299. ND_PRINT((ndo, "%smatch dl_vlan_pcp %s", pfx, pcp_str(*cp)));
  1300. cp += 1;
  1301. /* pad1 */
  1302. ND_TCHECK2(*cp, 1);
  1303. cp += 1;
  1304. /* dl_type */
  1305. ND_TCHECK2(*cp, 2);
  1306. dl_type = EXTRACT_16BITS(cp);
  1307. cp += 2;
  1308. if (! (wildcards & OFPFW_DL_TYPE))
  1309. ND_PRINT((ndo, "%smatch dl_type 0x%04x", pfx, dl_type));
  1310. /* nw_tos */
  1311. ND_TCHECK2(*cp, 1);
  1312. if (! (wildcards & OFPFW_NW_TOS))
  1313. ND_PRINT((ndo, "%smatch nw_tos 0x%02x", pfx, *cp));
  1314. cp += 1;
  1315. /* nw_proto */
  1316. ND_TCHECK2(*cp, 1);
  1317. nw_proto = *cp;
  1318. cp += 1;
  1319. if (! (wildcards & OFPFW_NW_PROTO)) {
  1320. field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP
  1321. ? "arp_opcode" : "nw_proto";
  1322. ND_PRINT((ndo, "%smatch %s %u", pfx, field_name, nw_proto));
  1323. }
  1324. /* pad2 */
  1325. ND_TCHECK2(*cp, 2);
  1326. cp += 2;
  1327. /* nw_src */
  1328. ND_TCHECK2(*cp, 4);
  1329. nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT;
  1330. if (nw_bits < 32)
  1331. ND_PRINT((ndo, "%smatch nw_src %s/%u", pfx, ipaddr_string(ndo, cp), 32 - nw_bits));
  1332. cp += 4;
  1333. /* nw_dst */
  1334. ND_TCHECK2(*cp, 4);
  1335. nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT;
  1336. if (nw_bits < 32)
  1337. ND_PRINT((ndo, "%smatch nw_dst %s/%u", pfx, ipaddr_string(ndo, cp), 32 - nw_bits));
  1338. cp += 4;
  1339. /* tp_src */
  1340. ND_TCHECK2(*cp, 2);
  1341. if (! (wildcards & OFPFW_TP_SRC)) {
  1342. field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
  1343. && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
  1344. ? "icmp_type" : "tp_src";
  1345. ND_PRINT((ndo, "%smatch %s %u", pfx, field_name, EXTRACT_16BITS(cp)));
  1346. }
  1347. cp += 2;
  1348. /* tp_dst */
  1349. ND_TCHECK2(*cp, 2);
  1350. if (! (wildcards & OFPFW_TP_DST)) {
  1351. field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
  1352. && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
  1353. ? "icmp_code" : "tp_dst";
  1354. ND_PRINT((ndo, "%smatch %s %u", pfx, field_name, EXTRACT_16BITS(cp)));
  1355. }
  1356. return cp + 2;
  1357. trunc:
  1358. ND_PRINT((ndo, "%s", tstr));
  1359. return ep;
  1360. }
  1361. /* [OF10] Section 5.2.4 */
  1362. static const u_char *
  1363. of10_actions_print(netdissect_options *ndo,
  1364. const char *pfx, const u_char *cp, const u_char *ep,
  1365. u_int len)
  1366. {
  1367. const u_char *cp0 = cp;
  1368. const u_int len0 = len;
  1369. uint16_t type, alen, output_port;
  1370. while (len) {
  1371. u_char alen_bogus = 0, skip = 0;
  1372. if (len < OF_ACTION_HEADER_LEN)
  1373. goto invalid;
  1374. /* type */
  1375. ND_TCHECK2(*cp, 2);
  1376. type = EXTRACT_16BITS(cp);
  1377. cp += 2;
  1378. ND_PRINT((ndo, "%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type)));
  1379. /* length */
  1380. ND_TCHECK2(*cp, 2);
  1381. alen = EXTRACT_16BITS(cp);
  1382. cp += 2;
  1383. ND_PRINT((ndo, ", len %u", alen));
  1384. /* On action size underrun/overrun skip the rest of the action list. */
  1385. if (alen < OF_ACTION_HEADER_LEN || alen > len)
  1386. goto invalid;
  1387. /* On action size inappropriate for the given type or invalid type just skip
  1388. * the current action, as the basic length constraint has been met. */
  1389. switch (type) {
  1390. case OFPAT_OUTPUT:
  1391. case OFPAT_SET_VLAN_VID:
  1392. case OFPAT_SET_VLAN_PCP:
  1393. case OFPAT_STRIP_VLAN:
  1394. case OFPAT_SET_NW_SRC:
  1395. case OFPAT_SET_NW_DST:
  1396. case OFPAT_SET_NW_TOS:
  1397. case OFPAT_SET_TP_SRC:
  1398. case OFPAT_SET_TP_DST:
  1399. alen_bogus = alen != 8;
  1400. break;
  1401. case OFPAT_SET_DL_SRC:
  1402. case OFPAT_SET_DL_DST:
  1403. case OFPAT_ENQUEUE:
  1404. alen_bogus = alen != 16;
  1405. break;
  1406. case OFPAT_VENDOR:
  1407. alen_bogus = alen % 8 != 0; /* already >= 8 so far */
  1408. break;
  1409. default:
  1410. skip = 1;
  1411. }
  1412. if (alen_bogus) {
  1413. ND_PRINT((ndo, " (bogus)"));
  1414. skip = 1;
  1415. }
  1416. if (skip) {
  1417. ND_TCHECK2(*cp, alen - 4);
  1418. cp += alen - 4;
  1419. goto next_action;
  1420. }
  1421. /* OK to decode the rest of the action structure */
  1422. switch (type) {
  1423. case OFPAT_OUTPUT:
  1424. /* port */
  1425. ND_TCHECK2(*cp, 2);
  1426. output_port = EXTRACT_16BITS(cp);
  1427. cp += 2;
  1428. ND_PRINT((ndo, ", port %s", tok2str(ofpp_str, "%u", output_port)));
  1429. /* max_len */
  1430. ND_TCHECK2(*cp, 2);
  1431. if (output_port == OFPP_CONTROLLER)
  1432. ND_PRINT((ndo, ", max_len %u", EXTRACT_16BITS(cp)));
  1433. cp += 2;
  1434. break;
  1435. case OFPAT_SET_VLAN_VID:
  1436. /* vlan_vid */
  1437. ND_TCHECK2(*cp, 2);
  1438. ND_PRINT((ndo, ", vlan_vid %s", vlan_str(EXTRACT_16BITS(cp))));
  1439. cp += 2;
  1440. /* pad */
  1441. ND_TCHECK2(*cp, 2);
  1442. cp += 2;
  1443. break;
  1444. case OFPAT_SET_VLAN_PCP:
  1445. /* vlan_pcp */
  1446. ND_TCHECK2(*cp, 1);
  1447. ND_PRINT((ndo, ", vlan_pcp %s", pcp_str(*cp)));
  1448. cp += 1;
  1449. /* pad */
  1450. ND_TCHECK2(*cp, 3);
  1451. cp += 3;
  1452. break;
  1453. case OFPAT_SET_DL_SRC:
  1454. case OFPAT_SET_DL_DST:
  1455. /* dl_addr */
  1456. ND_TCHECK2(*cp, ETHER_ADDR_LEN);
  1457. ND_PRINT((ndo, ", dl_addr %s", etheraddr_string(ndo, cp)));
  1458. cp += ETHER_ADDR_LEN;
  1459. /* pad */
  1460. ND_TCHECK2(*cp, 6);
  1461. cp += 6;
  1462. break;
  1463. case OFPAT_SET_NW_SRC:
  1464. case OFPAT_SET_NW_DST:
  1465. /* nw_addr */
  1466. ND_TCHECK2(*cp, 4);
  1467. ND_PRINT((ndo, ", nw_addr %s", ipaddr_string(ndo, cp)));
  1468. cp += 4;
  1469. break;
  1470. case OFPAT_SET_NW_TOS:
  1471. /* nw_tos */
  1472. ND_TCHECK2(*cp, 1);
  1473. ND_PRINT((ndo, ", nw_tos 0x%02x", *cp));
  1474. cp += 1;
  1475. /* pad */
  1476. ND_TCHECK2(*cp, 3);
  1477. cp += 3;
  1478. break;
  1479. case OFPAT_SET_TP_SRC:
  1480. case OFPAT_SET_TP_DST:
  1481. /* nw_tos */
  1482. ND_TCHECK2(*cp, 2);
  1483. ND_PRINT((ndo, ", tp_port %u", EXTRACT_16BITS(cp)));
  1484. cp += 2;
  1485. /* pad */
  1486. ND_TCHECK2(*cp, 2);
  1487. cp += 2;
  1488. break;
  1489. case OFPAT_ENQUEUE:
  1490. /* port */
  1491. ND_TCHECK2(*cp, 2);
  1492. ND_PRINT((ndo, ", port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1493. cp += 2;
  1494. /* pad */
  1495. ND_TCHECK2(*cp, 6);
  1496. cp += 6;
  1497. /* queue_id */
  1498. ND_TCHECK2(*cp, 4);
  1499. ND_PRINT((ndo, ", queue_id %s", tok2str(ofpq_str, "%u", EXTRACT_32BITS(cp))));
  1500. cp += 4;
  1501. break;
  1502. case OFPAT_VENDOR:
  1503. if (ep == (cp = of10_vendor_action_print(ndo, cp, ep, alen - 4)))
  1504. return ep; /* end of snapshot */
  1505. break;
  1506. case OFPAT_STRIP_VLAN:
  1507. /* pad */
  1508. ND_TCHECK2(*cp, 4);
  1509. cp += 4;
  1510. break;
  1511. } /* switch */
  1512. next_action:
  1513. len -= alen;
  1514. } /* while */
  1515. return cp;
  1516. invalid: /* skip the rest of actions */
  1517. ND_PRINT((ndo, "%s", istr));
  1518. ND_TCHECK2(*cp0, len0);
  1519. return cp0 + len0;
  1520. trunc:
  1521. ND_PRINT((ndo, "%s", tstr));
  1522. return ep;
  1523. }
  1524. /* [OF10] Section 5.3.1 */
  1525. static const u_char *
  1526. of10_features_reply_print(netdissect_options *ndo,
  1527. const u_char *cp, const u_char *ep, const u_int len)
  1528. {
  1529. /* datapath_id */
  1530. ND_TCHECK2(*cp, 8);
  1531. ND_PRINT((ndo, "\n\t dpid 0x%016" PRIx64, EXTRACT_64BITS(cp)));
  1532. cp += 8;
  1533. /* n_buffers */
  1534. ND_TCHECK2(*cp, 4);
  1535. ND_PRINT((ndo, ", n_buffers %u", EXTRACT_32BITS(cp)));
  1536. cp += 4;
  1537. /* n_tables */
  1538. ND_TCHECK2(*cp, 1);
  1539. ND_PRINT((ndo, ", n_tables %u", *cp));
  1540. cp += 1;
  1541. /* pad */
  1542. ND_TCHECK2(*cp, 3);
  1543. cp += 3;
  1544. /* capabilities */
  1545. ND_TCHECK2(*cp, 4);
  1546. ND_PRINT((ndo, "\n\t capabilities 0x%08x", EXTRACT_32BITS(cp)));
  1547. of10_bitmap_print(ndo, ofp_capabilities_bm, EXTRACT_32BITS(cp), OFPCAP_U);
  1548. cp += 4;
  1549. /* actions */
  1550. ND_TCHECK2(*cp, 4);
  1551. ND_PRINT((ndo, "\n\t actions 0x%08x", EXTRACT_32BITS(cp)));
  1552. of10_bitmap_print(ndo, ofpat_bm, EXTRACT_32BITS(cp), OFPAT_U);
  1553. cp += 4;
  1554. /* ports */
  1555. return of10_phy_ports_print(ndo, cp, ep, len - OF_SWITCH_FEATURES_LEN);
  1556. trunc:
  1557. ND_PRINT((ndo, "%s", tstr));
  1558. return ep;
  1559. }
  1560. /* [OF10] Section 5.3.3 */
  1561. static const u_char *
  1562. of10_flow_mod_print(netdissect_options *ndo,
  1563. const u_char *cp, const u_char *ep, const u_int len)
  1564. {
  1565. uint16_t command;
  1566. /* match */
  1567. if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep)))
  1568. return ep; /* end of snapshot */
  1569. /* cookie */
  1570. ND_TCHECK2(*cp, 8);
  1571. ND_PRINT((ndo, "\n\t cookie 0x%016" PRIx64, EXTRACT_64BITS(cp)));
  1572. cp += 8;
  1573. /* command */
  1574. ND_TCHECK2(*cp, 2);
  1575. command = EXTRACT_16BITS(cp);
  1576. ND_PRINT((ndo, ", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command)));
  1577. cp += 2;
  1578. /* idle_timeout */
  1579. ND_TCHECK2(*cp, 2);
  1580. if (EXTRACT_16BITS(cp))
  1581. ND_PRINT((ndo, ", idle_timeout %u", EXTRACT_16BITS(cp)));
  1582. cp += 2;
  1583. /* hard_timeout */
  1584. ND_TCHECK2(*cp, 2);
  1585. if (EXTRACT_16BITS(cp))
  1586. ND_PRINT((ndo, ", hard_timeout %u", EXTRACT_16BITS(cp)));
  1587. cp += 2;
  1588. /* priority */
  1589. ND_TCHECK2(*cp, 2);
  1590. if (EXTRACT_16BITS(cp))
  1591. ND_PRINT((ndo, ", priority %u", EXTRACT_16BITS(cp)));
  1592. cp += 2;
  1593. /* buffer_id */
  1594. ND_TCHECK2(*cp, 4);
  1595. if (command == OFPFC_ADD || command == OFPFC_MODIFY ||
  1596. command == OFPFC_MODIFY_STRICT)
  1597. ND_PRINT((ndo, ", buffer_id %s", tok2str(bufferid_str, "0x%08x", EXTRACT_32BITS(cp))));
  1598. cp += 4;
  1599. /* out_port */
  1600. ND_TCHECK2(*cp, 2);
  1601. if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT)
  1602. ND_PRINT((ndo, ", out_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1603. cp += 2;
  1604. /* flags */
  1605. ND_TCHECK2(*cp, 2);
  1606. ND_PRINT((ndo, ", flags 0x%04x", EXTRACT_16BITS(cp)));
  1607. of10_bitmap_print(ndo, ofpff_bm, EXTRACT_16BITS(cp), OFPFF_U);
  1608. cp += 2;
  1609. /* actions */
  1610. return of10_actions_print(ndo, "\n\t ", cp, ep, len - OF_FLOW_MOD_LEN);
  1611. trunc:
  1612. ND_PRINT((ndo, "%s", tstr));
  1613. return ep;
  1614. }
  1615. /* ibid */
  1616. static const u_char *
  1617. of10_port_mod_print(netdissect_options *ndo,
  1618. const u_char *cp, const u_char *ep)
  1619. {
  1620. /* port_no */
  1621. ND_TCHECK2(*cp, 2);
  1622. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1623. cp += 2;
  1624. /* hw_addr */
  1625. ND_TCHECK2(*cp, ETHER_ADDR_LEN);
  1626. ND_PRINT((ndo, ", hw_addr %s", etheraddr_string(ndo, cp)));
  1627. cp += ETHER_ADDR_LEN;
  1628. /* config */
  1629. ND_TCHECK2(*cp, 4);
  1630. ND_PRINT((ndo, "\n\t config 0x%08x", EXTRACT_32BITS(cp)));
  1631. of10_bitmap_print(ndo, ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U);
  1632. cp += 4;
  1633. /* mask */
  1634. ND_TCHECK2(*cp, 4);
  1635. ND_PRINT((ndo, "\n\t mask 0x%08x", EXTRACT_32BITS(cp)));
  1636. of10_bitmap_print(ndo, ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U);
  1637. cp += 4;
  1638. /* advertise */
  1639. ND_TCHECK2(*cp, 4);
  1640. ND_PRINT((ndo, "\n\t advertise 0x%08x", EXTRACT_32BITS(cp)));
  1641. of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U);
  1642. cp += 4;
  1643. /* pad */
  1644. ND_TCHECK2(*cp, 4);
  1645. return cp + 4;
  1646. trunc:
  1647. ND_PRINT((ndo, "%s", tstr));
  1648. return ep;
  1649. }
  1650. /* [OF10] Section 5.3.5 */
  1651. static const u_char *
  1652. of10_stats_request_print(netdissect_options *ndo,
  1653. const u_char *cp, const u_char *ep, u_int len)
  1654. {
  1655. const u_char *cp0 = cp;
  1656. const u_int len0 = len;
  1657. uint16_t type;
  1658. /* type */
  1659. ND_TCHECK2(*cp, 2);
  1660. type = EXTRACT_16BITS(cp);
  1661. cp += 2;
  1662. ND_PRINT((ndo, "\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)));
  1663. /* flags */
  1664. ND_TCHECK2(*cp, 2);
  1665. ND_PRINT((ndo, ", flags 0x%04x", EXTRACT_16BITS(cp)));
  1666. if (EXTRACT_16BITS(cp))
  1667. ND_PRINT((ndo, " (bogus)"));
  1668. cp += 2;
  1669. /* type-specific body of one of fixed lengths */
  1670. len -= OF_STATS_REQUEST_LEN;
  1671. switch(type) {
  1672. case OFPST_DESC:
  1673. case OFPST_TABLE:
  1674. if (len)
  1675. goto invalid;
  1676. return cp;
  1677. case OFPST_FLOW:
  1678. case OFPST_AGGREGATE:
  1679. if (len != OF_FLOW_STATS_REQUEST_LEN)
  1680. goto invalid;
  1681. /* match */
  1682. if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep)))
  1683. return ep; /* end of snapshot */
  1684. /* table_id */
  1685. ND_TCHECK2(*cp, 1);
  1686. ND_PRINT((ndo, "\n\t table_id %s", tok2str(tableid_str, "%u", *cp)));
  1687. cp += 1;
  1688. /* pad */
  1689. ND_TCHECK2(*cp, 1);
  1690. cp += 1;
  1691. /* out_port */
  1692. ND_TCHECK2(*cp, 2);
  1693. ND_PRINT((ndo, ", out_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1694. return cp + 2;
  1695. case OFPST_PORT:
  1696. if (len != OF_PORT_STATS_REQUEST_LEN)
  1697. goto invalid;
  1698. /* port_no */
  1699. ND_TCHECK2(*cp, 2);
  1700. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1701. cp += 2;
  1702. /* pad */
  1703. ND_TCHECK2(*cp, 6);
  1704. return cp + 6;
  1705. case OFPST_QUEUE:
  1706. if (len != OF_QUEUE_STATS_REQUEST_LEN)
  1707. goto invalid;
  1708. /* port_no */
  1709. ND_TCHECK2(*cp, 2);
  1710. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1711. cp += 2;
  1712. /* pad */
  1713. ND_TCHECK2(*cp, 2);
  1714. cp += 2;
  1715. /* queue_id */
  1716. ND_TCHECK2(*cp, 4);
  1717. ND_PRINT((ndo, ", queue_id %s", tok2str(ofpq_str, "%u", EXTRACT_32BITS(cp))));
  1718. return cp + 4;
  1719. case OFPST_VENDOR:
  1720. return of10_vendor_data_print(ndo, cp, ep, len);
  1721. }
  1722. return cp;
  1723. invalid: /* skip the message body */
  1724. ND_PRINT((ndo, "%s", istr));
  1725. ND_TCHECK2(*cp0, len0);
  1726. return cp0 + len0;
  1727. trunc:
  1728. ND_PRINT((ndo, "%s", tstr));
  1729. return ep;
  1730. }
  1731. /* ibid */
  1732. static const u_char *
  1733. of10_desc_stats_reply_print(netdissect_options *ndo,
  1734. const u_char *cp, const u_char *ep, const u_int len)
  1735. {
  1736. if (len != OF_DESC_STATS_LEN)
  1737. goto invalid;
  1738. /* mfr_desc */
  1739. ND_TCHECK2(*cp, DESC_STR_LEN);
  1740. ND_PRINT((ndo, "\n\t mfr_desc '"));
  1741. fn_print(ndo, cp, cp + DESC_STR_LEN);
  1742. ND_PRINT((ndo, "'"));
  1743. cp += DESC_STR_LEN;
  1744. /* hw_desc */
  1745. ND_TCHECK2(*cp, DESC_STR_LEN);
  1746. ND_PRINT((ndo, "\n\t hw_desc '"));
  1747. fn_print(ndo, cp, cp + DESC_STR_LEN);
  1748. ND_PRINT((ndo, "'"));
  1749. cp += DESC_STR_LEN;
  1750. /* sw_desc */
  1751. ND_TCHECK2(*cp, DESC_STR_LEN);
  1752. ND_PRINT((ndo, "\n\t sw_desc '"));
  1753. fn_print(ndo, cp, cp + DESC_STR_LEN);
  1754. ND_PRINT((ndo, "'"));
  1755. cp += DESC_STR_LEN;
  1756. /* serial_num */
  1757. ND_TCHECK2(*cp, SERIAL_NUM_LEN);
  1758. ND_PRINT((ndo, "\n\t serial_num '"));
  1759. fn_print(ndo, cp, cp + SERIAL_NUM_LEN);
  1760. ND_PRINT((ndo, "'"));
  1761. cp += SERIAL_NUM_LEN;
  1762. /* dp_desc */
  1763. ND_TCHECK2(*cp, DESC_STR_LEN);
  1764. ND_PRINT((ndo, "\n\t dp_desc '"));
  1765. fn_print(ndo, cp, cp + DESC_STR_LEN);
  1766. ND_PRINT((ndo, "'"));
  1767. return cp + DESC_STR_LEN;
  1768. invalid: /* skip the message body */
  1769. ND_PRINT((ndo, "%s", istr));
  1770. ND_TCHECK2(*cp, len);
  1771. return cp + len;
  1772. trunc:
  1773. ND_PRINT((ndo, "%s", tstr));
  1774. return ep;
  1775. }
  1776. /* ibid */
  1777. static const u_char *
  1778. of10_flow_stats_reply_print(netdissect_options *ndo,
  1779. const u_char *cp, const u_char *ep, u_int len)
  1780. {
  1781. const u_char *cp0 = cp;
  1782. const u_int len0 = len;
  1783. uint16_t entry_len;
  1784. while (len) {
  1785. if (len < OF_FLOW_STATS_LEN)
  1786. goto invalid;
  1787. /* length */
  1788. ND_TCHECK2(*cp, 2);
  1789. entry_len = EXTRACT_16BITS(cp);
  1790. ND_PRINT((ndo, "\n\t length %u", entry_len));
  1791. if (entry_len < OF_FLOW_STATS_LEN || entry_len > len)
  1792. goto invalid;
  1793. cp += 2;
  1794. /* table_id */
  1795. ND_TCHECK2(*cp, 1);
  1796. ND_PRINT((ndo, ", table_id %s", tok2str(tableid_str, "%u", *cp)));
  1797. cp += 1;
  1798. /* pad */
  1799. ND_TCHECK2(*cp, 1);
  1800. cp += 1;
  1801. /* match */
  1802. if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep)))
  1803. return ep; /* end of snapshot */
  1804. /* duration_sec */
  1805. ND_TCHECK2(*cp, 4);
  1806. ND_PRINT((ndo, "\n\t duration_sec %u", EXTRACT_32BITS(cp)));
  1807. cp += 4;
  1808. /* duration_nsec */
  1809. ND_TCHECK2(*cp, 4);
  1810. ND_PRINT((ndo, ", duration_nsec %u", EXTRACT_32BITS(cp)));
  1811. cp += 4;
  1812. /* priority */
  1813. ND_TCHECK2(*cp, 2);
  1814. ND_PRINT((ndo, ", priority %u", EXTRACT_16BITS(cp)));
  1815. cp += 2;
  1816. /* idle_timeout */
  1817. ND_TCHECK2(*cp, 2);
  1818. ND_PRINT((ndo, ", idle_timeout %u", EXTRACT_16BITS(cp)));
  1819. cp += 2;
  1820. /* hard_timeout */
  1821. ND_TCHECK2(*cp, 2);
  1822. ND_PRINT((ndo, ", hard_timeout %u", EXTRACT_16BITS(cp)));
  1823. cp += 2;
  1824. /* pad2 */
  1825. ND_TCHECK2(*cp, 6);
  1826. cp += 6;
  1827. /* cookie */
  1828. ND_TCHECK2(*cp, 8);
  1829. ND_PRINT((ndo, ", cookie 0x%016" PRIx64, EXTRACT_64BITS(cp)));
  1830. cp += 8;
  1831. /* packet_count */
  1832. ND_TCHECK2(*cp, 8);
  1833. ND_PRINT((ndo, ", packet_count %" PRIu64, EXTRACT_64BITS(cp)));
  1834. cp += 8;
  1835. /* byte_count */
  1836. ND_TCHECK2(*cp, 8);
  1837. ND_PRINT((ndo, ", byte_count %" PRIu64, EXTRACT_64BITS(cp)));
  1838. cp += 8;
  1839. /* actions */
  1840. if (ep == (cp = of10_actions_print(ndo, "\n\t ", cp, ep, entry_len - OF_FLOW_STATS_LEN)))
  1841. return ep; /* end of snapshot */
  1842. len -= entry_len;
  1843. } /* while */
  1844. return cp;
  1845. invalid: /* skip the rest of flow statistics entries */
  1846. ND_PRINT((ndo, "%s", istr));
  1847. ND_TCHECK2(*cp0, len0);
  1848. return cp0 + len0;
  1849. trunc:
  1850. ND_PRINT((ndo, "%s", tstr));
  1851. return ep;
  1852. }
  1853. /* ibid */
  1854. static const u_char *
  1855. of10_aggregate_stats_reply_print(netdissect_options *ndo,
  1856. const u_char *cp, const u_char *ep,
  1857. const u_int len)
  1858. {
  1859. if (len != OF_AGGREGATE_STATS_REPLY_LEN)
  1860. goto invalid;
  1861. /* packet_count */
  1862. ND_TCHECK2(*cp, 8);
  1863. ND_PRINT((ndo, "\n\t packet_count %" PRIu64, EXTRACT_64BITS(cp)));
  1864. cp += 8;
  1865. /* byte_count */
  1866. ND_TCHECK2(*cp, 8);
  1867. ND_PRINT((ndo, ", byte_count %" PRIu64, EXTRACT_64BITS(cp)));
  1868. cp += 8;
  1869. /* flow_count */
  1870. ND_TCHECK2(*cp, 4);
  1871. ND_PRINT((ndo, ", flow_count %u", EXTRACT_32BITS(cp)));
  1872. cp += 4;
  1873. /* pad */
  1874. ND_TCHECK2(*cp, 4);
  1875. return cp + 4;
  1876. invalid: /* skip the message body */
  1877. ND_PRINT((ndo, "%s", istr));
  1878. ND_TCHECK2(*cp, len);
  1879. return cp + len;
  1880. trunc:
  1881. ND_PRINT((ndo, "%s", tstr));
  1882. return ep;
  1883. }
  1884. /* ibid */
  1885. static const u_char *
  1886. of10_table_stats_reply_print(netdissect_options *ndo,
  1887. const u_char *cp, const u_char *ep, u_int len)
  1888. {
  1889. const u_char *cp0 = cp;
  1890. const u_int len0 = len;
  1891. while (len) {
  1892. if (len < OF_TABLE_STATS_LEN)
  1893. goto invalid;
  1894. /* table_id */
  1895. ND_TCHECK2(*cp, 1);
  1896. ND_PRINT((ndo, "\n\t table_id %s", tok2str(tableid_str, "%u", *cp)));
  1897. cp += 1;
  1898. /* pad */
  1899. ND_TCHECK2(*cp, 3);
  1900. cp += 3;
  1901. /* name */
  1902. ND_TCHECK2(*cp, OFP_MAX_TABLE_NAME_LEN);
  1903. ND_PRINT((ndo, ", name '"));
  1904. fn_print(ndo, cp, cp + OFP_MAX_TABLE_NAME_LEN);
  1905. ND_PRINT((ndo, "'"));
  1906. cp += OFP_MAX_TABLE_NAME_LEN;
  1907. /* wildcards */
  1908. ND_TCHECK2(*cp, 4);
  1909. ND_PRINT((ndo, "\n\t wildcards 0x%08x", EXTRACT_32BITS(cp)));
  1910. of10_bitmap_print(ndo, ofpfw_bm, EXTRACT_32BITS(cp), OFPFW_U);
  1911. cp += 4;
  1912. /* max_entries */
  1913. ND_TCHECK2(*cp, 4);
  1914. ND_PRINT((ndo, "\n\t max_entries %u", EXTRACT_32BITS(cp)));
  1915. cp += 4;
  1916. /* active_count */
  1917. ND_TCHECK2(*cp, 4);
  1918. ND_PRINT((ndo, ", active_count %u", EXTRACT_32BITS(cp)));
  1919. cp += 4;
  1920. /* lookup_count */
  1921. ND_TCHECK2(*cp, 8);
  1922. ND_PRINT((ndo, ", lookup_count %" PRIu64, EXTRACT_64BITS(cp)));
  1923. cp += 8;
  1924. /* matched_count */
  1925. ND_TCHECK2(*cp, 8);
  1926. ND_PRINT((ndo, ", matched_count %" PRIu64, EXTRACT_64BITS(cp)));
  1927. cp += 8;
  1928. len -= OF_TABLE_STATS_LEN;
  1929. } /* while */
  1930. return cp;
  1931. invalid: /* skip the undersized trailing data */
  1932. ND_PRINT((ndo, "%s", istr));
  1933. ND_TCHECK2(*cp0, len0);
  1934. return cp0 + len0;
  1935. trunc:
  1936. ND_PRINT((ndo, "%s", tstr));
  1937. return ep;
  1938. }
  1939. /* ibid */
  1940. static const u_char *
  1941. of10_port_stats_reply_print(netdissect_options *ndo,
  1942. const u_char *cp, const u_char *ep, u_int len)
  1943. {
  1944. const u_char *cp0 = cp;
  1945. const u_int len0 = len;
  1946. while (len) {
  1947. if (len < OF_PORT_STATS_LEN)
  1948. goto invalid;
  1949. /* port_no */
  1950. ND_TCHECK2(*cp, 2);
  1951. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  1952. cp += 2;
  1953. if (ndo->ndo_vflag < 2) {
  1954. ND_TCHECK2(*cp, OF_PORT_STATS_LEN - 2);
  1955. cp += OF_PORT_STATS_LEN - 2;
  1956. goto next_port;
  1957. }
  1958. /* pad */
  1959. ND_TCHECK2(*cp, 6);
  1960. cp += 6;
  1961. /* rx_packets */
  1962. ND_TCHECK2(*cp, 8);
  1963. ND_PRINT((ndo, ", rx_packets %" PRIu64, EXTRACT_64BITS(cp)));
  1964. cp += 8;
  1965. /* tx_packets */
  1966. ND_TCHECK2(*cp, 8);
  1967. ND_PRINT((ndo, ", tx_packets %" PRIu64, EXTRACT_64BITS(cp)));
  1968. cp += 8;
  1969. /* rx_bytes */
  1970. ND_TCHECK2(*cp, 8);
  1971. ND_PRINT((ndo, ", rx_bytes %" PRIu64, EXTRACT_64BITS(cp)));
  1972. cp += 8;
  1973. /* tx_bytes */
  1974. ND_TCHECK2(*cp, 8);
  1975. ND_PRINT((ndo, ", tx_bytes %" PRIu64, EXTRACT_64BITS(cp)));
  1976. cp += 8;
  1977. /* rx_dropped */
  1978. ND_TCHECK2(*cp, 8);
  1979. ND_PRINT((ndo, ", rx_dropped %" PRIu64, EXTRACT_64BITS(cp)));
  1980. cp += 8;
  1981. /* tx_dropped */
  1982. ND_TCHECK2(*cp, 8);
  1983. ND_PRINT((ndo, ", tx_dropped %" PRIu64, EXTRACT_64BITS(cp)));
  1984. cp += 8;
  1985. /* rx_errors */
  1986. ND_TCHECK2(*cp, 8);
  1987. ND_PRINT((ndo, ", rx_errors %" PRIu64, EXTRACT_64BITS(cp)));
  1988. cp += 8;
  1989. /* tx_errors */
  1990. ND_TCHECK2(*cp, 8);
  1991. ND_PRINT((ndo, ", tx_errors %" PRIu64, EXTRACT_64BITS(cp)));
  1992. cp += 8;
  1993. /* rx_frame_err */
  1994. ND_TCHECK2(*cp, 8);
  1995. ND_PRINT((ndo, ", rx_frame_err %" PRIu64, EXTRACT_64BITS(cp)));
  1996. cp += 8;
  1997. /* rx_over_err */
  1998. ND_TCHECK2(*cp, 8);
  1999. ND_PRINT((ndo, ", rx_over_err %" PRIu64, EXTRACT_64BITS(cp)));
  2000. cp += 8;
  2001. /* rx_crc_err */
  2002. ND_TCHECK2(*cp, 8);
  2003. ND_PRINT((ndo, ", rx_crc_err %" PRIu64, EXTRACT_64BITS(cp)));
  2004. cp += 8;
  2005. /* collisions */
  2006. ND_TCHECK2(*cp, 8);
  2007. ND_PRINT((ndo, ", collisions %" PRIu64, EXTRACT_64BITS(cp)));
  2008. cp += 8;
  2009. next_port:
  2010. len -= OF_PORT_STATS_LEN;
  2011. } /* while */
  2012. return cp;
  2013. invalid: /* skip the undersized trailing data */
  2014. ND_PRINT((ndo, "%s", istr));
  2015. ND_TCHECK2(*cp0, len0);
  2016. return cp0 + len0;
  2017. trunc:
  2018. ND_PRINT((ndo, "%s", tstr));
  2019. return ep;
  2020. }
  2021. /* ibid */
  2022. static const u_char *
  2023. of10_queue_stats_reply_print(netdissect_options *ndo,
  2024. const u_char *cp, const u_char *ep, u_int len)
  2025. {
  2026. const u_char *cp0 = cp;
  2027. const u_int len0 = len;
  2028. while (len) {
  2029. if (len < OF_QUEUE_STATS_LEN)
  2030. goto invalid;
  2031. /* port_no */
  2032. ND_TCHECK2(*cp, 2);
  2033. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  2034. cp += 2;
  2035. /* pad */
  2036. ND_TCHECK2(*cp, 2);
  2037. cp += 2;
  2038. /* queue_id */
  2039. ND_TCHECK2(*cp, 4);
  2040. ND_PRINT((ndo, ", queue_id %u", EXTRACT_32BITS(cp)));
  2041. cp += 4;
  2042. /* tx_bytes */
  2043. ND_TCHECK2(*cp, 8);
  2044. ND_PRINT((ndo, ", tx_bytes %" PRIu64, EXTRACT_64BITS(cp)));
  2045. cp += 8;
  2046. /* tx_packets */
  2047. ND_TCHECK2(*cp, 8);
  2048. ND_PRINT((ndo, ", tx_packets %" PRIu64, EXTRACT_64BITS(cp)));
  2049. cp += 8;
  2050. /* tx_errors */
  2051. ND_TCHECK2(*cp, 8);
  2052. ND_PRINT((ndo, ", tx_errors %" PRIu64, EXTRACT_64BITS(cp)));
  2053. cp += 8;
  2054. len -= OF_QUEUE_STATS_LEN;
  2055. } /* while */
  2056. return cp;
  2057. invalid: /* skip the undersized trailing data */
  2058. ND_PRINT((ndo, "%s", istr));
  2059. ND_TCHECK2(*cp0, len0);
  2060. return cp0 + len0;
  2061. trunc:
  2062. ND_PRINT((ndo, "%s", tstr));
  2063. return ep;
  2064. }
  2065. /* ibid */
  2066. static const u_char *
  2067. of10_stats_reply_print(netdissect_options *ndo,
  2068. const u_char *cp, const u_char *ep, const u_int len)
  2069. {
  2070. const u_char *cp0 = cp;
  2071. uint16_t type;
  2072. /* type */
  2073. ND_TCHECK2(*cp, 2);
  2074. type = EXTRACT_16BITS(cp);
  2075. ND_PRINT((ndo, "\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)));
  2076. cp += 2;
  2077. /* flags */
  2078. ND_TCHECK2(*cp, 2);
  2079. ND_PRINT((ndo, ", flags 0x%04x", EXTRACT_16BITS(cp)));
  2080. of10_bitmap_print(ndo, ofpsf_reply_bm, EXTRACT_16BITS(cp), OFPSF_REPLY_U);
  2081. cp += 2;
  2082. if (ndo->ndo_vflag > 0) {
  2083. const u_char *(*decoder)(netdissect_options *, const u_char *, const u_char *, u_int) =
  2084. type == OFPST_DESC ? of10_desc_stats_reply_print :
  2085. type == OFPST_FLOW ? of10_flow_stats_reply_print :
  2086. type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print :
  2087. type == OFPST_TABLE ? of10_table_stats_reply_print :
  2088. type == OFPST_PORT ? of10_port_stats_reply_print :
  2089. type == OFPST_QUEUE ? of10_queue_stats_reply_print :
  2090. type == OFPST_VENDOR ? of10_vendor_data_print :
  2091. NULL;
  2092. if (decoder != NULL)
  2093. return decoder(ndo, cp, ep, len - OF_STATS_REPLY_LEN);
  2094. }
  2095. ND_TCHECK2(*cp0, len);
  2096. return cp0 + len;
  2097. trunc:
  2098. ND_PRINT((ndo, "%s", tstr));
  2099. return ep;
  2100. }
  2101. /* [OF10] Section 5.3.6 */
  2102. static const u_char *
  2103. of10_packet_out_print(netdissect_options *ndo,
  2104. const u_char *cp, const u_char *ep, const u_int len)
  2105. {
  2106. const u_char *cp0 = cp;
  2107. const u_int len0 = len;
  2108. uint16_t actions_len;
  2109. /* buffer_id */
  2110. ND_TCHECK2(*cp, 4);
  2111. ND_PRINT((ndo, "\n\t buffer_id 0x%08x", EXTRACT_32BITS(cp)));
  2112. cp += 4;
  2113. /* in_port */
  2114. ND_TCHECK2(*cp, 2);
  2115. ND_PRINT((ndo, ", in_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  2116. cp += 2;
  2117. /* actions_len */
  2118. ND_TCHECK2(*cp, 2);
  2119. actions_len = EXTRACT_16BITS(cp);
  2120. cp += 2;
  2121. if (actions_len > len - OF_PACKET_OUT_LEN)
  2122. goto invalid;
  2123. /* actions */
  2124. if (ep == (cp = of10_actions_print(ndo, "\n\t ", cp, ep, actions_len)))
  2125. return ep; /* end of snapshot */
  2126. /* data */
  2127. return of10_packet_data_print(ndo, cp, ep, len - OF_PACKET_OUT_LEN - actions_len);
  2128. invalid: /* skip the rest of the message body */
  2129. ND_PRINT((ndo, "%s", istr));
  2130. ND_TCHECK2(*cp0, len0);
  2131. return cp0 + len0;
  2132. trunc:
  2133. ND_PRINT((ndo, "%s", tstr));
  2134. return ep;
  2135. }
  2136. /* [OF10] Section 5.4.1 */
  2137. static const u_char *
  2138. of10_packet_in_print(netdissect_options *ndo,
  2139. const u_char *cp, const u_char *ep, const u_int len)
  2140. {
  2141. /* buffer_id */
  2142. ND_TCHECK2(*cp, 4);
  2143. ND_PRINT((ndo, "\n\t buffer_id %s", tok2str(bufferid_str, "0x%08x", EXTRACT_32BITS(cp))));
  2144. cp += 4;
  2145. /* total_len */
  2146. ND_TCHECK2(*cp, 2);
  2147. ND_PRINT((ndo, ", total_len %u", EXTRACT_16BITS(cp)));
  2148. cp += 2;
  2149. /* in_port */
  2150. ND_TCHECK2(*cp, 2);
  2151. ND_PRINT((ndo, ", in_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  2152. cp += 2;
  2153. /* reason */
  2154. ND_TCHECK2(*cp, 1);
  2155. ND_PRINT((ndo, ", reason %s", tok2str(ofpr_str, "invalid (0x%02x)", *cp)));
  2156. cp += 1;
  2157. /* pad */
  2158. ND_TCHECK2(*cp, 1);
  2159. cp += 1;
  2160. /* data */
  2161. /* 2 mock octets count in OF_PACKET_IN_LEN but not in len */
  2162. return of10_packet_data_print(ndo, cp, ep, len - (OF_PACKET_IN_LEN - 2));
  2163. trunc:
  2164. ND_PRINT((ndo, "%s", tstr));
  2165. return ep;
  2166. }
  2167. /* [OF10] Section 5.4.2 */
  2168. static const u_char *
  2169. of10_flow_removed_print(netdissect_options *ndo,
  2170. const u_char *cp, const u_char *ep)
  2171. {
  2172. /* match */
  2173. if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep)))
  2174. return ep; /* end of snapshot */
  2175. /* cookie */
  2176. ND_TCHECK2(*cp, 8);
  2177. ND_PRINT((ndo, "\n\t cookie 0x%016" PRIx64, EXTRACT_64BITS(cp)));
  2178. cp += 8;
  2179. /* priority */
  2180. ND_TCHECK2(*cp, 2);
  2181. if (EXTRACT_16BITS(cp))
  2182. ND_PRINT((ndo, ", priority %u", EXTRACT_16BITS(cp)));
  2183. cp += 2;
  2184. /* reason */
  2185. ND_TCHECK2(*cp, 1);
  2186. ND_PRINT((ndo, ", reason %s", tok2str(ofprr_str, "unknown (0x%02x)", *cp)));
  2187. cp += 1;
  2188. /* pad */
  2189. ND_TCHECK2(*cp, 1);
  2190. cp += 1;
  2191. /* duration_sec */
  2192. ND_TCHECK2(*cp, 4);
  2193. ND_PRINT((ndo, ", duration_sec %u", EXTRACT_32BITS(cp)));
  2194. cp += 4;
  2195. /* duration_nsec */
  2196. ND_TCHECK2(*cp, 4);
  2197. ND_PRINT((ndo, ", duration_nsec %u", EXTRACT_32BITS(cp)));
  2198. cp += 4;
  2199. /* idle_timeout */
  2200. ND_TCHECK2(*cp, 2);
  2201. if (EXTRACT_16BITS(cp))
  2202. ND_PRINT((ndo, ", idle_timeout %u", EXTRACT_16BITS(cp)));
  2203. cp += 2;
  2204. /* pad2 */
  2205. ND_TCHECK2(*cp, 2);
  2206. cp += 2;
  2207. /* packet_count */
  2208. ND_TCHECK2(*cp, 8);
  2209. ND_PRINT((ndo, ", packet_count %" PRIu64, EXTRACT_64BITS(cp)));
  2210. cp += 8;
  2211. /* byte_count */
  2212. ND_TCHECK2(*cp, 8);
  2213. ND_PRINT((ndo, ", byte_count %" PRIu64, EXTRACT_64BITS(cp)));
  2214. return cp + 8;
  2215. trunc:
  2216. ND_PRINT((ndo, "%s", tstr));
  2217. return ep;
  2218. }
  2219. /* [OF10] Section 5.4.4 */
  2220. static const u_char *
  2221. of10_error_print(netdissect_options *ndo,
  2222. const u_char *cp, const u_char *ep, const u_int len)
  2223. {
  2224. uint16_t type;
  2225. const struct tok *code_str;
  2226. /* type */
  2227. ND_TCHECK2(*cp, 2);
  2228. type = EXTRACT_16BITS(cp);
  2229. cp += 2;
  2230. ND_PRINT((ndo, "\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type)));
  2231. /* code */
  2232. ND_TCHECK2(*cp, 2);
  2233. code_str =
  2234. type == OFPET_HELLO_FAILED ? ofphfc_str :
  2235. type == OFPET_BAD_REQUEST ? ofpbrc_str :
  2236. type == OFPET_BAD_ACTION ? ofpbac_str :
  2237. type == OFPET_FLOW_MOD_FAILED ? ofpfmfc_str :
  2238. type == OFPET_PORT_MOD_FAILED ? ofppmfc_str :
  2239. type == OFPET_QUEUE_OP_FAILED ? ofpqofc_str :
  2240. empty_str;
  2241. ND_PRINT((ndo, ", code %s", tok2str(code_str, "invalid (0x%04x)", EXTRACT_16BITS(cp))));
  2242. cp += 2;
  2243. /* data */
  2244. return of10_data_print(ndo, cp, ep, len - OF_ERROR_MSG_LEN);
  2245. trunc:
  2246. ND_PRINT((ndo, "%s", tstr));
  2247. return ep;
  2248. }
  2249. const u_char *
  2250. of10_header_body_print(netdissect_options *ndo,
  2251. const u_char *cp, const u_char *ep, const uint8_t type,
  2252. const uint16_t len, const uint32_t xid)
  2253. {
  2254. const u_char *cp0 = cp;
  2255. const u_int len0 = len;
  2256. /* Thus far message length is not less than the basic header size, but most
  2257. * message types have additional assorted constraints on the length. Wherever
  2258. * possible, check that message length meets the constraint, in remaining
  2259. * cases check that the length is OK to begin decoding and leave any final
  2260. * verification up to a lower-layer function. When the current message is
  2261. * invalid, proceed to the next message. */
  2262. /* [OF10] Section 5.1 */
  2263. ND_PRINT((ndo, "\n\tversion 1.0, type %s, length %u, xid 0x%08x",
  2264. tok2str(ofpt_str, "invalid (0x%02x)", type), len, xid));
  2265. switch (type) {
  2266. /* OpenFlow header only. */
  2267. case OFPT_FEATURES_REQUEST: /* [OF10] Section 5.3.1 */
  2268. case OFPT_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.2 */
  2269. case OFPT_BARRIER_REQUEST: /* [OF10] Section 5.3.7 */
  2270. case OFPT_BARRIER_REPLY: /* ibid */
  2271. if (len != OF_HEADER_LEN)
  2272. goto invalid;
  2273. break;
  2274. /* OpenFlow header and fixed-size message body. */
  2275. case OFPT_SET_CONFIG: /* [OF10] Section 5.3.2 */
  2276. case OFPT_GET_CONFIG_REPLY: /* ibid */
  2277. if (len != OF_SWITCH_CONFIG_LEN)
  2278. goto invalid;
  2279. if (ndo->ndo_vflag < 1)
  2280. goto next_message;
  2281. /* flags */
  2282. ND_TCHECK2(*cp, 2);
  2283. ND_PRINT((ndo, "\n\t flags %s", tok2str(ofp_config_str, "invalid (0x%04x)", EXTRACT_16BITS(cp))));
  2284. cp += 2;
  2285. /* miss_send_len */
  2286. ND_TCHECK2(*cp, 2);
  2287. ND_PRINT((ndo, ", miss_send_len %u", EXTRACT_16BITS(cp)));
  2288. return cp + 2;
  2289. case OFPT_PORT_MOD:
  2290. if (len != OF_PORT_MOD_LEN)
  2291. goto invalid;
  2292. if (ndo->ndo_vflag < 1)
  2293. goto next_message;
  2294. return of10_port_mod_print(ndo, cp, ep);
  2295. case OFPT_QUEUE_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.4 */
  2296. if (len != OF_QUEUE_GET_CONFIG_REQUEST_LEN)
  2297. goto invalid;
  2298. if (ndo->ndo_vflag < 1)
  2299. goto next_message;
  2300. /* port */
  2301. ND_TCHECK2(*cp, 2);
  2302. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  2303. cp += 2;
  2304. /* pad */
  2305. ND_TCHECK2(*cp, 2);
  2306. return cp + 2;
  2307. case OFPT_FLOW_REMOVED:
  2308. if (len != OF_FLOW_REMOVED_LEN)
  2309. goto invalid;
  2310. if (ndo->ndo_vflag < 1)
  2311. goto next_message;
  2312. return of10_flow_removed_print(ndo, cp, ep);
  2313. case OFPT_PORT_STATUS: /* [OF10] Section 5.4.3 */
  2314. if (len != OF_PORT_STATUS_LEN)
  2315. goto invalid;
  2316. if (ndo->ndo_vflag < 1)
  2317. goto next_message;
  2318. /* reason */
  2319. ND_TCHECK2(*cp, 1);
  2320. ND_PRINT((ndo, "\n\t reason %s", tok2str(ofppr_str, "invalid (0x%02x)", *cp)));
  2321. cp += 1;
  2322. /* pad */
  2323. ND_TCHECK2(*cp, 7);
  2324. cp += 7;
  2325. /* desc */
  2326. return of10_phy_ports_print(ndo, cp, ep, OF_PHY_PORT_LEN);
  2327. /* OpenFlow header, fixed-size message body and n * fixed-size data units. */
  2328. case OFPT_FEATURES_REPLY:
  2329. if (len < OF_SWITCH_FEATURES_LEN)
  2330. goto invalid;
  2331. if (ndo->ndo_vflag < 1)
  2332. goto next_message;
  2333. return of10_features_reply_print(ndo, cp, ep, len);
  2334. /* OpenFlow header and variable-size data. */
  2335. case OFPT_HELLO: /* [OF10] Section 5.5.1 */
  2336. case OFPT_ECHO_REQUEST: /* [OF10] Section 5.5.2 */
  2337. case OFPT_ECHO_REPLY: /* [OF10] Section 5.5.3 */
  2338. if (ndo->ndo_vflag < 1)
  2339. goto next_message;
  2340. return of10_data_print(ndo, cp, ep, len - OF_HEADER_LEN);
  2341. /* OpenFlow header, fixed-size message body and variable-size data. */
  2342. case OFPT_ERROR:
  2343. if (len < OF_ERROR_MSG_LEN)
  2344. goto invalid;
  2345. if (ndo->ndo_vflag < 1)
  2346. goto next_message;
  2347. return of10_error_print(ndo, cp, ep, len);
  2348. case OFPT_VENDOR:
  2349. /* [OF10] Section 5.5.4 */
  2350. if (len < OF_VENDOR_HEADER_LEN)
  2351. goto invalid;
  2352. if (ndo->ndo_vflag < 1)
  2353. goto next_message;
  2354. return of10_vendor_message_print(ndo, cp, ep, len - OF_HEADER_LEN);
  2355. case OFPT_PACKET_IN:
  2356. /* 2 mock octets count in OF_PACKET_IN_LEN but not in len */
  2357. if (len < OF_PACKET_IN_LEN - 2)
  2358. goto invalid;
  2359. if (ndo->ndo_vflag < 1)
  2360. goto next_message;
  2361. return of10_packet_in_print(ndo, cp, ep, len);
  2362. /* a. OpenFlow header. */
  2363. /* b. OpenFlow header and one of the fixed-size message bodies. */
  2364. /* c. OpenFlow header, fixed-size message body and variable-size data. */
  2365. case OFPT_STATS_REQUEST:
  2366. if (len < OF_STATS_REQUEST_LEN)
  2367. goto invalid;
  2368. if (ndo->ndo_vflag < 1)
  2369. goto next_message;
  2370. return of10_stats_request_print(ndo, cp, ep, len);
  2371. /* a. OpenFlow header and fixed-size message body. */
  2372. /* b. OpenFlow header and n * fixed-size data units. */
  2373. /* c. OpenFlow header and n * variable-size data units. */
  2374. /* d. OpenFlow header, fixed-size message body and variable-size data. */
  2375. case OFPT_STATS_REPLY:
  2376. if (len < OF_STATS_REPLY_LEN)
  2377. goto invalid;
  2378. if (ndo->ndo_vflag < 1)
  2379. goto next_message;
  2380. return of10_stats_reply_print(ndo, cp, ep, len);
  2381. /* OpenFlow header and n * variable-size data units and variable-size data. */
  2382. case OFPT_PACKET_OUT:
  2383. if (len < OF_PACKET_OUT_LEN)
  2384. goto invalid;
  2385. if (ndo->ndo_vflag < 1)
  2386. goto next_message;
  2387. return of10_packet_out_print(ndo, cp, ep, len);
  2388. /* OpenFlow header, fixed-size message body and n * variable-size data units. */
  2389. case OFPT_FLOW_MOD:
  2390. if (len < OF_FLOW_MOD_LEN)
  2391. goto invalid;
  2392. if (ndo->ndo_vflag < 1)
  2393. goto next_message;
  2394. return of10_flow_mod_print(ndo, cp, ep, len);
  2395. /* OpenFlow header, fixed-size message body and n * variable-size data units. */
  2396. case OFPT_QUEUE_GET_CONFIG_REPLY: /* [OF10] Section 5.3.4 */
  2397. if (len < OF_QUEUE_GET_CONFIG_REPLY_LEN)
  2398. goto invalid;
  2399. if (ndo->ndo_vflag < 1)
  2400. goto next_message;
  2401. /* port */
  2402. ND_TCHECK2(*cp, 2);
  2403. ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))));
  2404. cp += 2;
  2405. /* pad */
  2406. ND_TCHECK2(*cp, 6);
  2407. cp += 6;
  2408. /* queues */
  2409. return of10_queues_print(ndo, cp, ep, len - OF_QUEUE_GET_CONFIG_REPLY_LEN);
  2410. } /* switch (type) */
  2411. goto next_message;
  2412. invalid: /* skip the message body */
  2413. ND_PRINT((ndo, "%s", istr));
  2414. next_message:
  2415. ND_TCHECK2(*cp0, len0 - OF_HEADER_LEN);
  2416. return cp0 + len0 - OF_HEADER_LEN;
  2417. trunc:
  2418. ND_PRINT((ndo, "%s", tstr));
  2419. return ep;
  2420. }