ovs-dpctl.py 89 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775
  1. #!/usr/bin/env python3
  2. # SPDX-License-Identifier: GPL-2.0
  3. # Controls the openvswitch module. Part of the kselftest suite, but
  4. # can be used for some diagnostic purpose as well.
  5. import argparse
  6. import errno
  7. import ipaddress
  8. import logging
  9. import math
  10. import multiprocessing
  11. import re
  12. import socket
  13. import struct
  14. import sys
  15. import time
  16. import types
  17. import uuid
  18. try:
  19. from pyroute2 import NDB
  20. from pyroute2.netlink import NLA_F_NESTED
  21. from pyroute2.netlink import NLM_F_ACK
  22. from pyroute2.netlink import NLM_F_DUMP
  23. from pyroute2.netlink import NLM_F_REQUEST
  24. from pyroute2.netlink import genlmsg
  25. from pyroute2.netlink import nla
  26. from pyroute2.netlink import nlmsg_atoms
  27. from pyroute2.netlink.event import EventSocket
  28. from pyroute2.netlink.exceptions import NetlinkError
  29. from pyroute2.netlink.generic import GenericNetlinkSocket
  30. from pyroute2.netlink.nlsocket import Marshal
  31. import pyroute2
  32. import pyroute2.iproute
  33. except ModuleNotFoundError:
  34. print("Need to install the python pyroute2 package >= 0.6.")
  35. sys.exit(1)
  36. OVS_DATAPATH_FAMILY = "ovs_datapath"
  37. OVS_VPORT_FAMILY = "ovs_vport"
  38. OVS_FLOW_FAMILY = "ovs_flow"
  39. OVS_PACKET_FAMILY = "ovs_packet"
  40. OVS_METER_FAMILY = "ovs_meter"
  41. OVS_CT_LIMIT_FAMILY = "ovs_ct_limit"
  42. OVS_DATAPATH_VERSION = 2
  43. OVS_DP_CMD_NEW = 1
  44. OVS_DP_CMD_DEL = 2
  45. OVS_DP_CMD_GET = 3
  46. OVS_DP_CMD_SET = 4
  47. OVS_VPORT_CMD_NEW = 1
  48. OVS_VPORT_CMD_DEL = 2
  49. OVS_VPORT_CMD_GET = 3
  50. OVS_VPORT_CMD_SET = 4
  51. OVS_FLOW_CMD_NEW = 1
  52. OVS_FLOW_CMD_DEL = 2
  53. OVS_FLOW_CMD_GET = 3
  54. OVS_FLOW_CMD_SET = 4
  55. UINT32_MAX = 0xFFFFFFFF
  56. def macstr(mac):
  57. outstr = ":".join(["%02X" % i for i in mac])
  58. return outstr
  59. def strcspn(str1, str2):
  60. tot = 0
  61. for char in str1:
  62. if str2.find(char) != -1:
  63. return tot
  64. tot += 1
  65. return tot
  66. def strspn(str1, str2):
  67. tot = 0
  68. for char in str1:
  69. if str2.find(char) == -1:
  70. return tot
  71. tot += 1
  72. return tot
  73. def intparse(statestr, defmask="0xffffffff"):
  74. totalparse = strspn(statestr, "0123456789abcdefABCDEFx/")
  75. # scan until "/"
  76. count = strspn(statestr, "x0123456789abcdefABCDEF")
  77. firstnum = statestr[:count]
  78. if firstnum[-1] == "/":
  79. firstnum = firstnum[:-1]
  80. k = int(firstnum, 0)
  81. m = None
  82. if defmask is not None:
  83. secondnum = defmask
  84. if statestr[count] == "/":
  85. secondnum = statestr[count + 1 :] # this is wrong...
  86. m = int(secondnum, 0)
  87. return statestr[totalparse + 1 :], k, m
  88. def parse_flags(flag_str, flag_vals):
  89. bitResult = 0
  90. maskResult = 0
  91. if len(flag_str) == 0:
  92. return flag_str, bitResult, maskResult
  93. if flag_str[0].isdigit():
  94. idx = 0
  95. while flag_str[idx].isdigit() or flag_str[idx] == "x":
  96. idx += 1
  97. digits = flag_str[:idx]
  98. flag_str = flag_str[idx:]
  99. bitResult = int(digits, 0)
  100. maskResult = int(digits, 0)
  101. while len(flag_str) > 0 and (flag_str[0] == "+" or flag_str[0] == "-"):
  102. if flag_str[0] == "+":
  103. setFlag = True
  104. elif flag_str[0] == "-":
  105. setFlag = False
  106. flag_str = flag_str[1:]
  107. flag_len = 0
  108. while (
  109. flag_str[flag_len] != "+"
  110. and flag_str[flag_len] != "-"
  111. and flag_str[flag_len] != ","
  112. and flag_str[flag_len] != ")"
  113. ):
  114. flag_len += 1
  115. flag = flag_str[0:flag_len]
  116. if flag in flag_vals:
  117. if maskResult & flag_vals[flag]:
  118. raise KeyError(
  119. "Flag %s set once, cannot be set in multiples" % flag
  120. )
  121. if setFlag:
  122. bitResult |= flag_vals[flag]
  123. maskResult |= flag_vals[flag]
  124. else:
  125. raise KeyError("Missing flag value: %s" % flag)
  126. flag_str = flag_str[flag_len:]
  127. return flag_str, bitResult, maskResult
  128. def parse_ct_state(statestr):
  129. ct_flags = {
  130. "new": 1 << 0,
  131. "est": 1 << 1,
  132. "rel": 1 << 2,
  133. "rpl": 1 << 3,
  134. "inv": 1 << 4,
  135. "trk": 1 << 5,
  136. "snat": 1 << 6,
  137. "dnat": 1 << 7,
  138. }
  139. return parse_flags(statestr, ct_flags)
  140. def convert_mac(data):
  141. def to_bytes(mac):
  142. mac_split = mac.split(":")
  143. ret = bytearray([int(i, 16) for i in mac_split])
  144. return bytes(ret)
  145. mac_str, _, mask_str = data.partition('/')
  146. if not mac_str:
  147. mac_str = mask_str = "00:00:00:00:00:00"
  148. elif not mask_str:
  149. mask_str = "FF:FF:FF:FF:FF:FF"
  150. return to_bytes(mac_str), to_bytes(mask_str)
  151. def convert_ipv4(data):
  152. ip, _, mask = data.partition('/')
  153. if not ip:
  154. ip = mask = 0
  155. elif not mask:
  156. mask = 0xFFFFFFFF
  157. elif mask.isdigit():
  158. mask = (0xFFFFFFFF << (32 - int(mask))) & 0xFFFFFFFF
  159. return int(ipaddress.IPv4Address(ip)), int(ipaddress.IPv4Address(mask))
  160. def convert_ipv6(data):
  161. ip, _, mask = data.partition('/')
  162. if not ip:
  163. ip = mask = 0
  164. elif not mask:
  165. mask = 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'
  166. elif mask.isdigit():
  167. mask = ipaddress.IPv6Network("::/" + mask).hostmask
  168. return ipaddress.IPv6Address(ip).packed, ipaddress.IPv6Address(mask).packed
  169. def convert_int(size):
  170. def convert_int_sized(data):
  171. value, _, mask = data.partition('/')
  172. if not value:
  173. return 0, 0
  174. elif not mask:
  175. return int(value, 0), pow(2, size) - 1
  176. else:
  177. return int(value, 0), int(mask, 0)
  178. return convert_int_sized
  179. def parse_starts_block(block_str, scanstr, returnskipped, scanregex=False):
  180. if scanregex:
  181. m = re.search(scanstr, block_str)
  182. if m is None:
  183. if returnskipped:
  184. return block_str
  185. return False
  186. if returnskipped:
  187. block_str = block_str[len(m.group(0)) :]
  188. return block_str
  189. return True
  190. if block_str.startswith(scanstr):
  191. if returnskipped:
  192. block_str = block_str[len(scanstr) :]
  193. else:
  194. return True
  195. if returnskipped:
  196. return block_str
  197. return False
  198. def parse_extract_field(
  199. block_str, fieldstr, scanfmt, convert, masked=False, defval=None
  200. ):
  201. if fieldstr and not block_str.startswith(fieldstr):
  202. return block_str, defval
  203. if fieldstr:
  204. str_skiplen = len(fieldstr)
  205. str_skipped = block_str[str_skiplen:]
  206. if str_skiplen == 0:
  207. return str_skipped, defval
  208. else:
  209. str_skiplen = 0
  210. str_skipped = block_str
  211. m = re.search(scanfmt, str_skipped)
  212. if m is None:
  213. raise ValueError("Bad fmt string")
  214. data = m.group(0)
  215. if convert:
  216. data = convert(m.group(0))
  217. str_skipped = str_skipped[len(m.group(0)) :]
  218. if masked:
  219. if str_skipped[0] == "/":
  220. raise ValueError("Masking support TBD...")
  221. str_skipped = str_skipped[strspn(str_skipped, ", ") :]
  222. return str_skipped, data
  223. def parse_attrs(actstr, attr_desc):
  224. """Parses the given action string and returns a list of netlink
  225. attributes based on a list of attribute descriptions.
  226. Each element in the attribute description list is a tuple such as:
  227. (name, attr_name, parse_func)
  228. where:
  229. name: is the string representing the attribute
  230. attr_name: is the name of the attribute as defined in the uAPI.
  231. parse_func: is a callable accepting a string and returning either
  232. a single object (the parsed attribute value) or a tuple of
  233. two values (the parsed attribute value and the remaining string)
  234. Returns a list of attributes and the remaining string.
  235. """
  236. def parse_attr(actstr, key, func):
  237. actstr = actstr[len(key) :]
  238. if not func:
  239. return None, actstr
  240. delim = actstr[0]
  241. actstr = actstr[1:]
  242. if delim == "=":
  243. pos = strcspn(actstr, ",)")
  244. ret = func(actstr[:pos])
  245. else:
  246. ret = func(actstr)
  247. if isinstance(ret, tuple):
  248. (datum, actstr) = ret
  249. else:
  250. datum = ret
  251. actstr = actstr[strcspn(actstr, ",)"):]
  252. if delim == "(":
  253. if not actstr or actstr[0] != ")":
  254. raise ValueError("Action contains unbalanced parentheses")
  255. actstr = actstr[1:]
  256. actstr = actstr[strspn(actstr, ", ") :]
  257. return datum, actstr
  258. attrs = []
  259. attr_desc = list(attr_desc)
  260. while actstr and actstr[0] != ")" and attr_desc:
  261. found = False
  262. for i, (key, attr, func) in enumerate(attr_desc):
  263. if actstr.startswith(key):
  264. datum, actstr = parse_attr(actstr, key, func)
  265. attrs.append([attr, datum])
  266. found = True
  267. del attr_desc[i]
  268. if not found:
  269. raise ValueError("Unknown attribute: '%s'" % actstr)
  270. actstr = actstr[strspn(actstr, ", ") :]
  271. if actstr[0] != ")":
  272. raise ValueError("Action string contains extra garbage or has "
  273. "unbalanced parenthesis: '%s'" % actstr)
  274. return attrs, actstr[1:]
  275. class ovs_dp_msg(genlmsg):
  276. # include the OVS version
  277. # We need a custom header rather than just being able to rely on
  278. # genlmsg because fields ends up not expressing everything correctly
  279. # if we use the canonical example of setting fields = (('customfield',),)
  280. fields = genlmsg.fields + (("dpifindex", "I"),)
  281. class ovsactions(nla):
  282. nla_flags = NLA_F_NESTED
  283. nla_map = (
  284. ("OVS_ACTION_ATTR_UNSPEC", "none"),
  285. ("OVS_ACTION_ATTR_OUTPUT", "uint32"),
  286. ("OVS_ACTION_ATTR_USERSPACE", "userspace"),
  287. ("OVS_ACTION_ATTR_SET", "ovskey"),
  288. ("OVS_ACTION_ATTR_PUSH_VLAN", "none"),
  289. ("OVS_ACTION_ATTR_POP_VLAN", "flag"),
  290. ("OVS_ACTION_ATTR_SAMPLE", "sample"),
  291. ("OVS_ACTION_ATTR_RECIRC", "uint32"),
  292. ("OVS_ACTION_ATTR_HASH", "none"),
  293. ("OVS_ACTION_ATTR_PUSH_MPLS", "none"),
  294. ("OVS_ACTION_ATTR_POP_MPLS", "flag"),
  295. ("OVS_ACTION_ATTR_SET_MASKED", "ovskey"),
  296. ("OVS_ACTION_ATTR_CT", "ctact"),
  297. ("OVS_ACTION_ATTR_TRUNC", "uint32"),
  298. ("OVS_ACTION_ATTR_PUSH_ETH", "none"),
  299. ("OVS_ACTION_ATTR_POP_ETH", "flag"),
  300. ("OVS_ACTION_ATTR_CT_CLEAR", "flag"),
  301. ("OVS_ACTION_ATTR_PUSH_NSH", "none"),
  302. ("OVS_ACTION_ATTR_POP_NSH", "flag"),
  303. ("OVS_ACTION_ATTR_METER", "none"),
  304. ("OVS_ACTION_ATTR_CLONE", "recursive"),
  305. ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"),
  306. ("OVS_ACTION_ATTR_ADD_MPLS", "none"),
  307. ("OVS_ACTION_ATTR_DEC_TTL", "none"),
  308. ("OVS_ACTION_ATTR_DROP", "uint32"),
  309. ("OVS_ACTION_ATTR_PSAMPLE", "psample"),
  310. )
  311. class psample(nla):
  312. nla_flags = NLA_F_NESTED
  313. nla_map = (
  314. ("OVS_PSAMPLE_ATTR_UNSPEC", "none"),
  315. ("OVS_PSAMPLE_ATTR_GROUP", "uint32"),
  316. ("OVS_PSAMPLE_ATTR_COOKIE", "array(uint8)"),
  317. )
  318. def dpstr(self, more=False):
  319. args = "group=%d" % self.get_attr("OVS_PSAMPLE_ATTR_GROUP")
  320. cookie = self.get_attr("OVS_PSAMPLE_ATTR_COOKIE")
  321. if cookie:
  322. args += ",cookie(%s)" % \
  323. "".join(format(x, "02x") for x in cookie)
  324. return "psample(%s)" % args
  325. def parse(self, actstr):
  326. desc = (
  327. ("group", "OVS_PSAMPLE_ATTR_GROUP", int),
  328. ("cookie", "OVS_PSAMPLE_ATTR_COOKIE",
  329. lambda x: list(bytearray.fromhex(x)))
  330. )
  331. attrs, actstr = parse_attrs(actstr, desc)
  332. for attr in attrs:
  333. self["attrs"].append(attr)
  334. return actstr
  335. class sample(nla):
  336. nla_flags = NLA_F_NESTED
  337. nla_map = (
  338. ("OVS_SAMPLE_ATTR_UNSPEC", "none"),
  339. ("OVS_SAMPLE_ATTR_PROBABILITY", "uint32"),
  340. ("OVS_SAMPLE_ATTR_ACTIONS", "ovsactions"),
  341. )
  342. def dpstr(self, more=False):
  343. args = []
  344. args.append("sample={:.2f}%".format(
  345. 100 * self.get_attr("OVS_SAMPLE_ATTR_PROBABILITY") /
  346. UINT32_MAX))
  347. actions = self.get_attr("OVS_SAMPLE_ATTR_ACTIONS")
  348. if actions:
  349. args.append("actions(%s)" % actions.dpstr(more))
  350. return "sample(%s)" % ",".join(args)
  351. def parse(self, actstr):
  352. def parse_nested_actions(actstr):
  353. subacts = ovsactions()
  354. parsed_len = subacts.parse(actstr)
  355. return subacts, actstr[parsed_len :]
  356. def percent_to_rate(percent):
  357. percent = float(percent.strip('%'))
  358. return int(math.floor(UINT32_MAX * (percent / 100.0) + .5))
  359. desc = (
  360. ("sample", "OVS_SAMPLE_ATTR_PROBABILITY", percent_to_rate),
  361. ("actions", "OVS_SAMPLE_ATTR_ACTIONS", parse_nested_actions),
  362. )
  363. attrs, actstr = parse_attrs(actstr, desc)
  364. for attr in attrs:
  365. self["attrs"].append(attr)
  366. return actstr
  367. class ctact(nla):
  368. nla_flags = NLA_F_NESTED
  369. nla_map = (
  370. ("OVS_CT_ATTR_NONE", "none"),
  371. ("OVS_CT_ATTR_COMMIT", "flag"),
  372. ("OVS_CT_ATTR_ZONE", "uint16"),
  373. ("OVS_CT_ATTR_MARK", "none"),
  374. ("OVS_CT_ATTR_LABELS", "none"),
  375. ("OVS_CT_ATTR_HELPER", "asciiz"),
  376. ("OVS_CT_ATTR_NAT", "natattr"),
  377. ("OVS_CT_ATTR_FORCE_COMMIT", "flag"),
  378. ("OVS_CT_ATTR_EVENTMASK", "uint32"),
  379. ("OVS_CT_ATTR_TIMEOUT", "asciiz"),
  380. )
  381. class natattr(nla):
  382. nla_flags = NLA_F_NESTED
  383. nla_map = (
  384. ("OVS_NAT_ATTR_NONE", "none"),
  385. ("OVS_NAT_ATTR_SRC", "flag"),
  386. ("OVS_NAT_ATTR_DST", "flag"),
  387. ("OVS_NAT_ATTR_IP_MIN", "ipaddr"),
  388. ("OVS_NAT_ATTR_IP_MAX", "ipaddr"),
  389. ("OVS_NAT_ATTR_PROTO_MIN", "uint16"),
  390. ("OVS_NAT_ATTR_PROTO_MAX", "uint16"),
  391. ("OVS_NAT_ATTR_PERSISTENT", "flag"),
  392. ("OVS_NAT_ATTR_PROTO_HASH", "flag"),
  393. ("OVS_NAT_ATTR_PROTO_RANDOM", "flag"),
  394. )
  395. def dpstr(self, more=False):
  396. print_str = "nat("
  397. if self.get_attr("OVS_NAT_ATTR_SRC"):
  398. print_str += "src"
  399. elif self.get_attr("OVS_NAT_ATTR_DST"):
  400. print_str += "dst"
  401. else:
  402. print_str += "XXX-unknown-nat"
  403. if self.get_attr("OVS_NAT_ATTR_IP_MIN") or self.get_attr(
  404. "OVS_NAT_ATTR_IP_MAX"
  405. ):
  406. if self.get_attr("OVS_NAT_ATTR_IP_MIN"):
  407. print_str += "=%s," % str(
  408. self.get_attr("OVS_NAT_ATTR_IP_MIN")
  409. )
  410. if self.get_attr("OVS_NAT_ATTR_IP_MAX"):
  411. print_str += "-%s," % str(
  412. self.get_attr("OVS_NAT_ATTR_IP_MAX")
  413. )
  414. else:
  415. print_str += ","
  416. if self.get_attr("OVS_NAT_ATTR_PROTO_MIN"):
  417. print_str += "proto_min=%d," % self.get_attr(
  418. "OVS_NAT_ATTR_PROTO_MIN"
  419. )
  420. if self.get_attr("OVS_NAT_ATTR_PROTO_MAX"):
  421. print_str += "proto_max=%d," % self.get_attr(
  422. "OVS_NAT_ATTR_PROTO_MAX"
  423. )
  424. if self.get_attr("OVS_NAT_ATTR_PERSISTENT"):
  425. print_str += "persistent,"
  426. if self.get_attr("OVS_NAT_ATTR_HASH"):
  427. print_str += "hash,"
  428. if self.get_attr("OVS_NAT_ATTR_RANDOM"):
  429. print_str += "random"
  430. print_str += ")"
  431. return print_str
  432. def dpstr(self, more=False):
  433. print_str = "ct("
  434. if self.get_attr("OVS_CT_ATTR_COMMIT") is not None:
  435. print_str += "commit,"
  436. if self.get_attr("OVS_CT_ATTR_ZONE") is not None:
  437. print_str += "zone=%d," % self.get_attr("OVS_CT_ATTR_ZONE")
  438. if self.get_attr("OVS_CT_ATTR_HELPER") is not None:
  439. print_str += "helper=%s," % self.get_attr("OVS_CT_ATTR_HELPER")
  440. if self.get_attr("OVS_CT_ATTR_NAT") is not None:
  441. print_str += self.get_attr("OVS_CT_ATTR_NAT").dpstr(more)
  442. print_str += ","
  443. if self.get_attr("OVS_CT_ATTR_FORCE_COMMIT") is not None:
  444. print_str += "force,"
  445. if self.get_attr("OVS_CT_ATTR_EVENTMASK") is not None:
  446. print_str += "emask=0x%X," % self.get_attr(
  447. "OVS_CT_ATTR_EVENTMASK"
  448. )
  449. if self.get_attr("OVS_CT_ATTR_TIMEOUT") is not None:
  450. print_str += "timeout=%s" % self.get_attr(
  451. "OVS_CT_ATTR_TIMEOUT"
  452. )
  453. print_str += ")"
  454. return print_str
  455. class userspace(nla):
  456. nla_flags = NLA_F_NESTED
  457. nla_map = (
  458. ("OVS_USERSPACE_ATTR_UNUSED", "none"),
  459. ("OVS_USERSPACE_ATTR_PID", "uint32"),
  460. ("OVS_USERSPACE_ATTR_USERDATA", "array(uint8)"),
  461. ("OVS_USERSPACE_ATTR_EGRESS_TUN_PORT", "uint32"),
  462. )
  463. def dpstr(self, more=False):
  464. print_str = "userspace("
  465. if self.get_attr("OVS_USERSPACE_ATTR_PID") is not None:
  466. print_str += "pid=%d," % self.get_attr(
  467. "OVS_USERSPACE_ATTR_PID"
  468. )
  469. if self.get_attr("OVS_USERSPACE_ATTR_USERDATA") is not None:
  470. print_str += "userdata="
  471. for f in self.get_attr("OVS_USERSPACE_ATTR_USERDATA"):
  472. print_str += "%x." % f
  473. if self.get_attr("OVS_USERSPACE_ATTR_EGRESS_TUN_PORT") is not None:
  474. print_str += "egress_tun_port=%d" % self.get_attr(
  475. "OVS_USERSPACE_ATTR_EGRESS_TUN_PORT"
  476. )
  477. print_str += ")"
  478. return print_str
  479. def parse(self, actstr):
  480. attrs_desc = (
  481. ("pid", "OVS_USERSPACE_ATTR_PID", int),
  482. ("userdata", "OVS_USERSPACE_ATTR_USERDATA",
  483. lambda x: list(bytearray.fromhex(x))),
  484. ("egress_tun_port", "OVS_USERSPACE_ATTR_EGRESS_TUN_PORT", int)
  485. )
  486. attrs, actstr = parse_attrs(actstr, attrs_desc)
  487. for attr in attrs:
  488. self["attrs"].append(attr)
  489. return actstr
  490. def dpstr(self, more=False):
  491. print_str = ""
  492. for field in self["attrs"]:
  493. if field[1] == "none" or self.get_attr(field[0]) is None:
  494. continue
  495. if print_str != "":
  496. print_str += ","
  497. if field[0] == "OVS_ACTION_ATTR_OUTPUT":
  498. print_str += "%d" % int(self.get_attr(field[0]))
  499. elif field[0] == "OVS_ACTION_ATTR_RECIRC":
  500. print_str += "recirc(0x%x)" % int(self.get_attr(field[0]))
  501. elif field[0] == "OVS_ACTION_ATTR_TRUNC":
  502. print_str += "trunc(%d)" % int(self.get_attr(field[0]))
  503. elif field[0] == "OVS_ACTION_ATTR_DROP":
  504. print_str += "drop(%d)" % int(self.get_attr(field[0]))
  505. elif field[0] == "OVS_ACTION_ATTR_CT_CLEAR":
  506. print_str += "ct_clear"
  507. elif field[0] == "OVS_ACTION_ATTR_POP_VLAN":
  508. print_str += "pop_vlan"
  509. elif field[0] == "OVS_ACTION_ATTR_POP_ETH":
  510. print_str += "pop_eth"
  511. elif field[0] == "OVS_ACTION_ATTR_POP_NSH":
  512. print_str += "pop_nsh"
  513. elif field[0] == "OVS_ACTION_ATTR_POP_MPLS":
  514. print_str += "pop_mpls"
  515. else:
  516. datum = self.get_attr(field[0])
  517. if field[0] == "OVS_ACTION_ATTR_CLONE":
  518. print_str += "clone("
  519. print_str += datum.dpstr(more)
  520. print_str += ")"
  521. elif field[0] == "OVS_ACTION_ATTR_SET" or \
  522. field[0] == "OVS_ACTION_ATTR_SET_MASKED":
  523. print_str += "set"
  524. field = datum
  525. mask = None
  526. if field[0] == "OVS_ACTION_ATTR_SET_MASKED":
  527. print_str += "_masked"
  528. field = datum[0]
  529. mask = datum[1]
  530. print_str += "("
  531. print_str += field.dpstr(mask, more)
  532. print_str += ")"
  533. else:
  534. try:
  535. print_str += datum.dpstr(more)
  536. except:
  537. print_str += "{ATTR: %s not decoded}" % field[0]
  538. return print_str
  539. def parse(self, actstr):
  540. totallen = len(actstr)
  541. while len(actstr) != 0:
  542. parsed = False
  543. parencount = 0
  544. if actstr.startswith("drop"):
  545. # If no reason is provided, the implicit drop is used (i.e no
  546. # action). If some reason is given, an explicit action is used.
  547. reason = None
  548. if actstr.startswith("drop("):
  549. parencount += 1
  550. actstr, reason = parse_extract_field(
  551. actstr,
  552. "drop(",
  553. r"([0-9]+)",
  554. lambda x: int(x, 0),
  555. False,
  556. None,
  557. )
  558. if reason is not None:
  559. self["attrs"].append(["OVS_ACTION_ATTR_DROP", reason])
  560. parsed = True
  561. else:
  562. actstr = actstr[len("drop"): ]
  563. return (totallen - len(actstr))
  564. elif parse_starts_block(actstr, r"^(\d+)", False, True):
  565. actstr, output = parse_extract_field(
  566. actstr, None, r"(\d+)", lambda x: int(x), False, "0"
  567. )
  568. self["attrs"].append(["OVS_ACTION_ATTR_OUTPUT", output])
  569. parsed = True
  570. elif parse_starts_block(actstr, "recirc(", False):
  571. actstr, recircid = parse_extract_field(
  572. actstr,
  573. "recirc(",
  574. r"([0-9a-fA-Fx]+)",
  575. lambda x: int(x, 0),
  576. False,
  577. 0,
  578. )
  579. parencount += 1
  580. self["attrs"].append(["OVS_ACTION_ATTR_RECIRC", recircid])
  581. parsed = True
  582. parse_flat_map = (
  583. ("ct_clear", "OVS_ACTION_ATTR_CT_CLEAR"),
  584. ("pop_vlan", "OVS_ACTION_ATTR_POP_VLAN"),
  585. ("pop_eth", "OVS_ACTION_ATTR_POP_ETH"),
  586. ("pop_nsh", "OVS_ACTION_ATTR_POP_NSH"),
  587. )
  588. for flat_act in parse_flat_map:
  589. if parse_starts_block(actstr, flat_act[0], False):
  590. actstr = actstr[len(flat_act[0]):]
  591. self["attrs"].append([flat_act[1], True])
  592. actstr = actstr[strspn(actstr, ", ") :]
  593. parsed = True
  594. if parse_starts_block(actstr, "clone(", False):
  595. parencount += 1
  596. subacts = ovsactions()
  597. actstr = actstr[len("clone("):]
  598. parsedLen = subacts.parse(actstr)
  599. lst = []
  600. self["attrs"].append(("OVS_ACTION_ATTR_CLONE", subacts))
  601. actstr = actstr[parsedLen:]
  602. parsed = True
  603. elif parse_starts_block(actstr, "set(", False):
  604. parencount += 1
  605. k = ovskey()
  606. actstr = actstr[len("set("):]
  607. actstr = k.parse(actstr, None)
  608. self["attrs"].append(("OVS_ACTION_ATTR_SET", k))
  609. if not actstr.startswith(")"):
  610. actstr = ")" + actstr
  611. parsed = True
  612. elif parse_starts_block(actstr, "set_masked(", False):
  613. parencount += 1
  614. k = ovskey()
  615. m = ovskey()
  616. actstr = actstr[len("set_masked("):]
  617. actstr = k.parse(actstr, m)
  618. self["attrs"].append(("OVS_ACTION_ATTR_SET_MASKED", [k, m]))
  619. if not actstr.startswith(")"):
  620. actstr = ")" + actstr
  621. parsed = True
  622. elif parse_starts_block(actstr, "ct(", False):
  623. parencount += 1
  624. actstr = actstr[len("ct(") :]
  625. ctact = ovsactions.ctact()
  626. for scan in (
  627. ("commit", "OVS_CT_ATTR_COMMIT", None),
  628. ("force_commit", "OVS_CT_ATTR_FORCE_COMMIT", None),
  629. ("zone", "OVS_CT_ATTR_ZONE", int),
  630. ("mark", "OVS_CT_ATTR_MARK", int),
  631. ("helper", "OVS_CT_ATTR_HELPER", lambda x, y: str(x)),
  632. ("timeout", "OVS_CT_ATTR_TIMEOUT", lambda x, y: str(x)),
  633. ):
  634. if actstr.startswith(scan[0]):
  635. actstr = actstr[len(scan[0]) :]
  636. if scan[2] is not None:
  637. if actstr[0] != "=":
  638. raise ValueError("Invalid ct attr")
  639. actstr = actstr[1:]
  640. pos = strcspn(actstr, ",)")
  641. datum = scan[2](actstr[:pos], 0)
  642. ctact["attrs"].append([scan[1], datum])
  643. actstr = actstr[pos:]
  644. else:
  645. ctact["attrs"].append([scan[1], None])
  646. actstr = actstr[strspn(actstr, ", ") :]
  647. # it seems strange to put this here, but nat() is a complex
  648. # sub-action and this lets it sit anywhere in the ct() action
  649. if actstr.startswith("nat"):
  650. actstr = actstr[3:]
  651. natact = ovsactions.ctact.natattr()
  652. if actstr.startswith("("):
  653. parencount += 1
  654. t = None
  655. actstr = actstr[1:]
  656. if actstr.startswith("src"):
  657. t = "OVS_NAT_ATTR_SRC"
  658. actstr = actstr[3:]
  659. elif actstr.startswith("dst"):
  660. t = "OVS_NAT_ATTR_DST"
  661. actstr = actstr[3:]
  662. actstr, ip_block_min = parse_extract_field(
  663. actstr, "=", r"([0-9a-fA-F\.]+)", str, False
  664. )
  665. actstr, ip_block_max = parse_extract_field(
  666. actstr, "-", r"([0-9a-fA-F\.]+)", str, False
  667. )
  668. actstr, proto_min = parse_extract_field(
  669. actstr, ":", r"(\d+)", int, False
  670. )
  671. actstr, proto_max = parse_extract_field(
  672. actstr, "-", r"(\d+)", int, False
  673. )
  674. if t is not None:
  675. natact["attrs"].append([t, None])
  676. if ip_block_min is not None:
  677. natact["attrs"].append(
  678. ["OVS_NAT_ATTR_IP_MIN", ip_block_min]
  679. )
  680. if ip_block_max is not None:
  681. natact["attrs"].append(
  682. ["OVS_NAT_ATTR_IP_MAX", ip_block_max]
  683. )
  684. if proto_min is not None:
  685. natact["attrs"].append(
  686. ["OVS_NAT_ATTR_PROTO_MIN", proto_min]
  687. )
  688. if proto_max is not None:
  689. natact["attrs"].append(
  690. ["OVS_NAT_ATTR_PROTO_MAX", proto_max]
  691. )
  692. for natscan in (
  693. ("persistent", "OVS_NAT_ATTR_PERSISTENT"),
  694. ("hash", "OVS_NAT_ATTR_PROTO_HASH"),
  695. ("random", "OVS_NAT_ATTR_PROTO_RANDOM"),
  696. ):
  697. if actstr.startswith(natscan[0]):
  698. actstr = actstr[len(natscan[0]) :]
  699. natact["attrs"].append([natscan[1], None])
  700. actstr = actstr[strspn(actstr, ", ") :]
  701. ctact["attrs"].append(["OVS_CT_ATTR_NAT", natact])
  702. actstr = actstr[strspn(actstr, ", ") :]
  703. self["attrs"].append(["OVS_ACTION_ATTR_CT", ctact])
  704. parsed = True
  705. elif parse_starts_block(actstr, "sample(", False):
  706. sampleact = self.sample()
  707. actstr = sampleact.parse(actstr[len("sample(") : ])
  708. self["attrs"].append(["OVS_ACTION_ATTR_SAMPLE", sampleact])
  709. parsed = True
  710. elif parse_starts_block(actstr, "psample(", False):
  711. psampleact = self.psample()
  712. actstr = psampleact.parse(actstr[len("psample(") : ])
  713. self["attrs"].append(["OVS_ACTION_ATTR_PSAMPLE", psampleact])
  714. parsed = True
  715. elif parse_starts_block(actstr, "userspace(", False):
  716. uact = self.userspace()
  717. actstr = uact.parse(actstr[len("userspace(") : ])
  718. self["attrs"].append(["OVS_ACTION_ATTR_USERSPACE", uact])
  719. parsed = True
  720. elif parse_starts_block(actstr, "trunc(", False):
  721. parencount += 1
  722. actstr, val = parse_extract_field(
  723. actstr,
  724. "trunc(",
  725. r"([0-9]+)",
  726. int,
  727. False,
  728. None,
  729. )
  730. self["attrs"].append(["OVS_ACTION_ATTR_TRUNC", val])
  731. parsed = True
  732. actstr = actstr[strspn(actstr, ", ") :]
  733. while parencount > 0:
  734. parencount -= 1
  735. actstr = actstr[strspn(actstr, " "):]
  736. if len(actstr) and actstr[0] != ")":
  737. raise ValueError("Action str: '%s' unbalanced" % actstr)
  738. actstr = actstr[1:]
  739. if len(actstr) and actstr[0] == ")":
  740. return (totallen - len(actstr))
  741. actstr = actstr[strspn(actstr, ", ") :]
  742. if not parsed:
  743. raise ValueError("Action str: '%s' not supported" % actstr)
  744. return (totallen - len(actstr))
  745. class ovskey(nla):
  746. nla_flags = NLA_F_NESTED
  747. nla_map = (
  748. ("OVS_KEY_ATTR_UNSPEC", "none"),
  749. ("OVS_KEY_ATTR_ENCAP", "none"),
  750. ("OVS_KEY_ATTR_PRIORITY", "uint32"),
  751. ("OVS_KEY_ATTR_IN_PORT", "uint32"),
  752. ("OVS_KEY_ATTR_ETHERNET", "ethaddr"),
  753. ("OVS_KEY_ATTR_VLAN", "uint16"),
  754. ("OVS_KEY_ATTR_ETHERTYPE", "be16"),
  755. ("OVS_KEY_ATTR_IPV4", "ovs_key_ipv4"),
  756. ("OVS_KEY_ATTR_IPV6", "ovs_key_ipv6"),
  757. ("OVS_KEY_ATTR_TCP", "ovs_key_tcp"),
  758. ("OVS_KEY_ATTR_UDP", "ovs_key_udp"),
  759. ("OVS_KEY_ATTR_ICMP", "ovs_key_icmp"),
  760. ("OVS_KEY_ATTR_ICMPV6", "ovs_key_icmpv6"),
  761. ("OVS_KEY_ATTR_ARP", "ovs_key_arp"),
  762. ("OVS_KEY_ATTR_ND", "ovs_key_nd"),
  763. ("OVS_KEY_ATTR_SKB_MARK", "uint32"),
  764. ("OVS_KEY_ATTR_TUNNEL", "ovs_key_tunnel"),
  765. ("OVS_KEY_ATTR_SCTP", "ovs_key_sctp"),
  766. ("OVS_KEY_ATTR_TCP_FLAGS", "be16"),
  767. ("OVS_KEY_ATTR_DP_HASH", "uint32"),
  768. ("OVS_KEY_ATTR_RECIRC_ID", "uint32"),
  769. ("OVS_KEY_ATTR_MPLS", "array(ovs_key_mpls)"),
  770. ("OVS_KEY_ATTR_CT_STATE", "uint32"),
  771. ("OVS_KEY_ATTR_CT_ZONE", "uint16"),
  772. ("OVS_KEY_ATTR_CT_MARK", "uint32"),
  773. ("OVS_KEY_ATTR_CT_LABELS", "none"),
  774. ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4", "ovs_key_ct_tuple_ipv4"),
  775. ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6", "ovs_key_ct_tuple_ipv6"),
  776. ("OVS_KEY_ATTR_NSH", "none"),
  777. ("OVS_KEY_ATTR_PACKET_TYPE", "none"),
  778. ("OVS_KEY_ATTR_ND_EXTENSIONS", "none"),
  779. ("OVS_KEY_ATTR_TUNNEL_INFO", "none"),
  780. ("OVS_KEY_ATTR_IPV6_EXTENSIONS", "none"),
  781. )
  782. class ovs_key_proto(nla):
  783. fields = (
  784. ("src", "!H"),
  785. ("dst", "!H"),
  786. )
  787. fields_map = (
  788. ("src", "src", "%d", lambda x: int(x) if x else 0,
  789. convert_int(16)),
  790. ("dst", "dst", "%d", lambda x: int(x) if x else 0,
  791. convert_int(16)),
  792. )
  793. def __init__(
  794. self,
  795. protostr,
  796. data=None,
  797. offset=None,
  798. parent=None,
  799. length=None,
  800. init=None,
  801. ):
  802. self.proto_str = protostr
  803. nla.__init__(
  804. self,
  805. data=data,
  806. offset=offset,
  807. parent=parent,
  808. length=length,
  809. init=init,
  810. )
  811. def parse(self, flowstr, typeInst):
  812. if not flowstr.startswith(self.proto_str):
  813. return None, None
  814. k = typeInst()
  815. m = typeInst()
  816. flowstr = flowstr[len(self.proto_str) :]
  817. if flowstr.startswith("("):
  818. flowstr = flowstr[1:]
  819. keybits = b""
  820. maskbits = b""
  821. for f in self.fields_map:
  822. if flowstr.startswith(f[1]):
  823. # the following assumes that the field looks
  824. # something like 'field.' where '.' is a
  825. # character that we don't exactly care about.
  826. flowstr = flowstr[len(f[1]) + 1 :]
  827. splitchar = 0
  828. for c in flowstr:
  829. if c == "," or c == ")":
  830. break
  831. splitchar += 1
  832. data = flowstr[:splitchar]
  833. flowstr = flowstr[splitchar:]
  834. else:
  835. data = ""
  836. if len(f) > 4:
  837. k[f[0]], m[f[0]] = f[4](data)
  838. else:
  839. k[f[0]] = f[3](data)
  840. m[f[0]] = f[3](data)
  841. flowstr = flowstr[strspn(flowstr, ", ") :]
  842. if len(flowstr) == 0:
  843. return flowstr, k, m
  844. flowstr = flowstr[strspn(flowstr, "), ") :]
  845. return flowstr, k, m
  846. def dpstr(self, masked=None, more=False):
  847. outstr = self.proto_str + "("
  848. first = False
  849. for f in self.fields_map:
  850. if first:
  851. outstr += ","
  852. if masked is None:
  853. outstr += "%s=" % f[0]
  854. if isinstance(f[2], str):
  855. outstr += f[2] % self[f[1]]
  856. else:
  857. outstr += f[2](self[f[1]])
  858. first = True
  859. elif more or f[3](masked[f[1]]) != 0:
  860. outstr += "%s=" % f[0]
  861. if isinstance(f[2], str):
  862. outstr += f[2] % self[f[1]]
  863. else:
  864. outstr += f[2](self[f[1]])
  865. outstr += "/"
  866. if isinstance(f[2], str):
  867. outstr += f[2] % masked[f[1]]
  868. else:
  869. outstr += f[2](masked[f[1]])
  870. first = True
  871. outstr += ")"
  872. return outstr
  873. class ethaddr(ovs_key_proto):
  874. fields = (
  875. ("src", "!6s"),
  876. ("dst", "!6s"),
  877. )
  878. fields_map = (
  879. (
  880. "src",
  881. "src",
  882. macstr,
  883. lambda x: int.from_bytes(x, "big"),
  884. convert_mac,
  885. ),
  886. (
  887. "dst",
  888. "dst",
  889. macstr,
  890. lambda x: int.from_bytes(x, "big"),
  891. convert_mac,
  892. ),
  893. )
  894. def __init__(
  895. self,
  896. data=None,
  897. offset=None,
  898. parent=None,
  899. length=None,
  900. init=None,
  901. ):
  902. ovskey.ovs_key_proto.__init__(
  903. self,
  904. "eth",
  905. data=data,
  906. offset=offset,
  907. parent=parent,
  908. length=length,
  909. init=init,
  910. )
  911. class ovs_key_ipv4(ovs_key_proto):
  912. fields = (
  913. ("src", "!I"),
  914. ("dst", "!I"),
  915. ("proto", "B"),
  916. ("tos", "B"),
  917. ("ttl", "B"),
  918. ("frag", "B"),
  919. )
  920. fields_map = (
  921. (
  922. "src",
  923. "src",
  924. lambda x: str(ipaddress.IPv4Address(x)),
  925. int,
  926. convert_ipv4,
  927. ),
  928. (
  929. "dst",
  930. "dst",
  931. lambda x: str(ipaddress.IPv4Address(x)),
  932. int,
  933. convert_ipv4,
  934. ),
  935. ("proto", "proto", "%d", lambda x: int(x) if x else 0,
  936. convert_int(8)),
  937. ("tos", "tos", "%d", lambda x: int(x) if x else 0,
  938. convert_int(8)),
  939. ("ttl", "ttl", "%d", lambda x: int(x) if x else 0,
  940. convert_int(8)),
  941. ("frag", "frag", "%d", lambda x: int(x) if x else 0,
  942. convert_int(8)),
  943. )
  944. def __init__(
  945. self,
  946. data=None,
  947. offset=None,
  948. parent=None,
  949. length=None,
  950. init=None,
  951. ):
  952. ovskey.ovs_key_proto.__init__(
  953. self,
  954. "ipv4",
  955. data=data,
  956. offset=offset,
  957. parent=parent,
  958. length=length,
  959. init=init,
  960. )
  961. class ovs_key_ipv6(ovs_key_proto):
  962. fields = (
  963. ("src", "!16s"),
  964. ("dst", "!16s"),
  965. ("label", "!I"),
  966. ("proto", "B"),
  967. ("tclass", "B"),
  968. ("hlimit", "B"),
  969. ("frag", "B"),
  970. )
  971. fields_map = (
  972. (
  973. "src",
  974. "src",
  975. lambda x: str(ipaddress.IPv6Address(x)),
  976. lambda x: ipaddress.IPv6Address(x).packed if x else 0,
  977. convert_ipv6,
  978. ),
  979. (
  980. "dst",
  981. "dst",
  982. lambda x: str(ipaddress.IPv6Address(x)),
  983. lambda x: ipaddress.IPv6Address(x).packed if x else 0,
  984. convert_ipv6,
  985. ),
  986. ("label", "label", "%d", lambda x: int(x) if x else 0),
  987. ("proto", "proto", "%d", lambda x: int(x) if x else 0),
  988. ("tclass", "tclass", "%d", lambda x: int(x) if x else 0),
  989. ("hlimit", "hlimit", "%d", lambda x: int(x) if x else 0),
  990. ("frag", "frag", "%d", lambda x: int(x) if x else 0),
  991. )
  992. def __init__(
  993. self,
  994. data=None,
  995. offset=None,
  996. parent=None,
  997. length=None,
  998. init=None,
  999. ):
  1000. ovskey.ovs_key_proto.__init__(
  1001. self,
  1002. "ipv6",
  1003. data=data,
  1004. offset=offset,
  1005. parent=parent,
  1006. length=length,
  1007. init=init,
  1008. )
  1009. class ovs_key_tcp(ovs_key_proto):
  1010. def __init__(
  1011. self,
  1012. data=None,
  1013. offset=None,
  1014. parent=None,
  1015. length=None,
  1016. init=None,
  1017. ):
  1018. ovskey.ovs_key_proto.__init__(
  1019. self,
  1020. "tcp",
  1021. data=data,
  1022. offset=offset,
  1023. parent=parent,
  1024. length=length,
  1025. init=init,
  1026. )
  1027. class ovs_key_udp(ovs_key_proto):
  1028. def __init__(
  1029. self,
  1030. data=None,
  1031. offset=None,
  1032. parent=None,
  1033. length=None,
  1034. init=None,
  1035. ):
  1036. ovskey.ovs_key_proto.__init__(
  1037. self,
  1038. "udp",
  1039. data=data,
  1040. offset=offset,
  1041. parent=parent,
  1042. length=length,
  1043. init=init,
  1044. )
  1045. class ovs_key_sctp(ovs_key_proto):
  1046. def __init__(
  1047. self,
  1048. data=None,
  1049. offset=None,
  1050. parent=None,
  1051. length=None,
  1052. init=None,
  1053. ):
  1054. ovskey.ovs_key_proto.__init__(
  1055. self,
  1056. "sctp",
  1057. data=data,
  1058. offset=offset,
  1059. parent=parent,
  1060. length=length,
  1061. init=init,
  1062. )
  1063. class ovs_key_icmp(ovs_key_proto):
  1064. fields = (
  1065. ("type", "B"),
  1066. ("code", "B"),
  1067. )
  1068. fields_map = (
  1069. ("type", "type", "%d", lambda x: int(x) if x else 0),
  1070. ("code", "code", "%d", lambda x: int(x) if x else 0),
  1071. )
  1072. def __init__(
  1073. self,
  1074. data=None,
  1075. offset=None,
  1076. parent=None,
  1077. length=None,
  1078. init=None,
  1079. ):
  1080. ovskey.ovs_key_proto.__init__(
  1081. self,
  1082. "icmp",
  1083. data=data,
  1084. offset=offset,
  1085. parent=parent,
  1086. length=length,
  1087. init=init,
  1088. )
  1089. class ovs_key_icmpv6(ovs_key_icmp):
  1090. def __init__(
  1091. self,
  1092. data=None,
  1093. offset=None,
  1094. parent=None,
  1095. length=None,
  1096. init=None,
  1097. ):
  1098. ovskey.ovs_key_proto.__init__(
  1099. self,
  1100. "icmpv6",
  1101. data=data,
  1102. offset=offset,
  1103. parent=parent,
  1104. length=length,
  1105. init=init,
  1106. )
  1107. class ovs_key_arp(ovs_key_proto):
  1108. fields = (
  1109. ("sip", "!I"),
  1110. ("tip", "!I"),
  1111. ("op", "!H"),
  1112. ("sha", "!6s"),
  1113. ("tha", "!6s"),
  1114. ("pad", "xx"),
  1115. )
  1116. fields_map = (
  1117. (
  1118. "sip",
  1119. "sip",
  1120. lambda x: str(ipaddress.IPv4Address(x)),
  1121. int,
  1122. convert_ipv4,
  1123. ),
  1124. (
  1125. "tip",
  1126. "tip",
  1127. lambda x: str(ipaddress.IPv4Address(x)),
  1128. int,
  1129. convert_ipv4,
  1130. ),
  1131. ("op", "op", "%d", lambda x: int(x) if x else 0),
  1132. (
  1133. "sha",
  1134. "sha",
  1135. macstr,
  1136. lambda x: int.from_bytes(x, "big"),
  1137. convert_mac,
  1138. ),
  1139. (
  1140. "tha",
  1141. "tha",
  1142. macstr,
  1143. lambda x: int.from_bytes(x, "big"),
  1144. convert_mac,
  1145. ),
  1146. )
  1147. def __init__(
  1148. self,
  1149. data=None,
  1150. offset=None,
  1151. parent=None,
  1152. length=None,
  1153. init=None,
  1154. ):
  1155. ovskey.ovs_key_proto.__init__(
  1156. self,
  1157. "arp",
  1158. data=data,
  1159. offset=offset,
  1160. parent=parent,
  1161. length=length,
  1162. init=init,
  1163. )
  1164. class ovs_key_nd(ovs_key_proto):
  1165. fields = (
  1166. ("target", "!16s"),
  1167. ("sll", "!6s"),
  1168. ("tll", "!6s"),
  1169. )
  1170. fields_map = (
  1171. (
  1172. "target",
  1173. "target",
  1174. lambda x: str(ipaddress.IPv6Address(x)),
  1175. convert_ipv6,
  1176. ),
  1177. ("sll", "sll", macstr, lambda x: int.from_bytes(x, "big")),
  1178. ("tll", "tll", macstr, lambda x: int.from_bytes(x, "big")),
  1179. )
  1180. def __init__(
  1181. self,
  1182. data=None,
  1183. offset=None,
  1184. parent=None,
  1185. length=None,
  1186. init=None,
  1187. ):
  1188. ovskey.ovs_key_proto.__init__(
  1189. self,
  1190. "nd",
  1191. data=data,
  1192. offset=offset,
  1193. parent=parent,
  1194. length=length,
  1195. init=init,
  1196. )
  1197. class ovs_key_ct_tuple_ipv4(ovs_key_proto):
  1198. fields = (
  1199. ("src", "!I"),
  1200. ("dst", "!I"),
  1201. ("tp_src", "!H"),
  1202. ("tp_dst", "!H"),
  1203. ("proto", "B"),
  1204. )
  1205. fields_map = (
  1206. (
  1207. "src",
  1208. "src",
  1209. lambda x: str(ipaddress.IPv4Address(x)),
  1210. int,
  1211. convert_ipv4,
  1212. ),
  1213. (
  1214. "dst",
  1215. "dst",
  1216. lambda x: str(ipaddress.IPv4Address(x)),
  1217. int,
  1218. convert_ipv4,
  1219. ),
  1220. ("tp_src", "tp_src", "%d", int),
  1221. ("tp_dst", "tp_dst", "%d", int),
  1222. ("proto", "proto", "%d", int),
  1223. )
  1224. def __init__(
  1225. self,
  1226. data=None,
  1227. offset=None,
  1228. parent=None,
  1229. length=None,
  1230. init=None,
  1231. ):
  1232. ovskey.ovs_key_proto.__init__(
  1233. self,
  1234. "ct_tuple4",
  1235. data=data,
  1236. offset=offset,
  1237. parent=parent,
  1238. length=length,
  1239. init=init,
  1240. )
  1241. class ovs_key_ct_tuple_ipv6(nla):
  1242. fields = (
  1243. ("src", "!16s"),
  1244. ("dst", "!16s"),
  1245. ("tp_src", "!H"),
  1246. ("tp_dst", "!H"),
  1247. ("proto", "B"),
  1248. )
  1249. fields_map = (
  1250. (
  1251. "src",
  1252. "src",
  1253. lambda x: str(ipaddress.IPv6Address(x)),
  1254. convert_ipv6,
  1255. ),
  1256. (
  1257. "dst",
  1258. "dst",
  1259. lambda x: str(ipaddress.IPv6Address(x)),
  1260. convert_ipv6,
  1261. ),
  1262. ("tp_src", "tp_src", "%d", int),
  1263. ("tp_dst", "tp_dst", "%d", int),
  1264. ("proto", "proto", "%d", int),
  1265. )
  1266. def __init__(
  1267. self,
  1268. data=None,
  1269. offset=None,
  1270. parent=None,
  1271. length=None,
  1272. init=None,
  1273. ):
  1274. ovskey.ovs_key_proto.__init__(
  1275. self,
  1276. "ct_tuple6",
  1277. data=data,
  1278. offset=offset,
  1279. parent=parent,
  1280. length=length,
  1281. init=init,
  1282. )
  1283. class ovs_key_tunnel(nla):
  1284. nla_flags = NLA_F_NESTED
  1285. nla_map = (
  1286. ("OVS_TUNNEL_KEY_ATTR_ID", "be64"),
  1287. ("OVS_TUNNEL_KEY_ATTR_IPV4_SRC", "ipaddr"),
  1288. ("OVS_TUNNEL_KEY_ATTR_IPV4_DST", "ipaddr"),
  1289. ("OVS_TUNNEL_KEY_ATTR_TOS", "uint8"),
  1290. ("OVS_TUNNEL_KEY_ATTR_TTL", "uint8"),
  1291. ("OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT", "flag"),
  1292. ("OVS_TUNNEL_KEY_ATTR_CSUM", "flag"),
  1293. ("OVS_TUNNEL_KEY_ATTR_OAM", "flag"),
  1294. ("OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS", "array(uint32)"),
  1295. ("OVS_TUNNEL_KEY_ATTR_TP_SRC", "be16"),
  1296. ("OVS_TUNNEL_KEY_ATTR_TP_DST", "be16"),
  1297. ("OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS", "none"),
  1298. ("OVS_TUNNEL_KEY_ATTR_IPV6_SRC", "ipaddr"),
  1299. ("OVS_TUNNEL_KEY_ATTR_IPV6_DST", "ipaddr"),
  1300. ("OVS_TUNNEL_KEY_ATTR_PAD", "none"),
  1301. ("OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS", "none"),
  1302. ("OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE", "flag"),
  1303. )
  1304. def parse(self, flowstr, mask=None):
  1305. if not flowstr.startswith("tunnel("):
  1306. return None, None
  1307. k = ovskey.ovs_key_tunnel()
  1308. if mask is not None:
  1309. mask = ovskey.ovs_key_tunnel()
  1310. flowstr = flowstr[len("tunnel("):]
  1311. v6_address = None
  1312. fields = [
  1313. ("tun_id=", r"(\d+)", int, "OVS_TUNNEL_KEY_ATTR_ID",
  1314. 0xffffffffffffffff, None, None),
  1315. ("src=", r"([0-9a-fA-F\.]+)", str,
  1316. "OVS_TUNNEL_KEY_ATTR_IPV4_SRC", "255.255.255.255", "0.0.0.0",
  1317. False),
  1318. ("dst=", r"([0-9a-fA-F\.]+)", str,
  1319. "OVS_TUNNEL_KEY_ATTR_IPV4_DST", "255.255.255.255", "0.0.0.0",
  1320. False),
  1321. ("ipv6_src=", r"([0-9a-fA-F:]+)", str,
  1322. "OVS_TUNNEL_KEY_ATTR_IPV6_SRC",
  1323. "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::", True),
  1324. ("ipv6_dst=", r"([0-9a-fA-F:]+)", str,
  1325. "OVS_TUNNEL_KEY_ATTR_IPV6_DST",
  1326. "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::", True),
  1327. ("tos=", r"(\d+)", int, "OVS_TUNNEL_KEY_ATTR_TOS", 255, 0,
  1328. None),
  1329. ("ttl=", r"(\d+)", int, "OVS_TUNNEL_KEY_ATTR_TTL", 255, 0,
  1330. None),
  1331. ("tp_src=", r"(\d+)", int, "OVS_TUNNEL_KEY_ATTR_TP_SRC",
  1332. 65535, 0, None),
  1333. ("tp_dst=", r"(\d+)", int, "OVS_TUNNEL_KEY_ATTR_TP_DST",
  1334. 65535, 0, None),
  1335. ]
  1336. forced_include = ["OVS_TUNNEL_KEY_ATTR_TTL"]
  1337. for prefix, regex, typ, attr_name, mask_val, default_val, v46_flag in fields:
  1338. flowstr, value = parse_extract_field(flowstr, prefix, regex, typ, False)
  1339. if not attr_name:
  1340. raise Exception("Bad list value in tunnel fields")
  1341. if value is None and attr_name in forced_include:
  1342. value = default_val
  1343. mask_val = default_val
  1344. if value is not None:
  1345. if v46_flag is not None:
  1346. if v6_address is None:
  1347. v6_address = v46_flag
  1348. if v46_flag != v6_address:
  1349. raise ValueError("Cannot mix v6 and v4 addresses")
  1350. k["attrs"].append([attr_name, value])
  1351. if mask is not None:
  1352. mask["attrs"].append([attr_name, mask_val])
  1353. else:
  1354. if v46_flag is not None:
  1355. if v6_address is None or v46_flag != v6_address:
  1356. continue
  1357. if mask is not None:
  1358. mask["attrs"].append([attr_name, default_val])
  1359. if k["attrs"][0][0] != "OVS_TUNNEL_KEY_ATTR_ID":
  1360. raise ValueError("Needs a tunid set")
  1361. if flowstr.startswith("flags("):
  1362. flowstr = flowstr[len("flags("):]
  1363. flagspos = flowstr.find(")")
  1364. flags = flowstr[:flagspos]
  1365. flowstr = flowstr[flagspos + 1:]
  1366. flag_attrs = {
  1367. "df": "OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT",
  1368. "csum": "OVS_TUNNEL_KEY_ATTR_CSUM",
  1369. "oam": "OVS_TUNNEL_KEY_ATTR_OAM"
  1370. }
  1371. for flag in flags.split("|"):
  1372. if flag in flag_attrs:
  1373. k["attrs"].append([flag_attrs[flag], True])
  1374. if mask is not None:
  1375. mask["attrs"].append([flag_attrs[flag], True])
  1376. flowstr = flowstr[strspn(flowstr, ", ") :]
  1377. return flowstr, k, mask
  1378. def dpstr(self, mask=None, more=False):
  1379. print_str = "tunnel("
  1380. flagsattrs = []
  1381. for k in self["attrs"]:
  1382. noprint = False
  1383. if k[0] == "OVS_TUNNEL_KEY_ATTR_ID":
  1384. print_str += "tun_id=%d" % k[1]
  1385. elif k[0] == "OVS_TUNNEL_KEY_ATTR_IPV4_SRC":
  1386. print_str += "src=%s" % k[1]
  1387. elif k[0] == "OVS_TUNNEL_KEY_ATTR_IPV4_DST":
  1388. print_str += "dst=%s" % k[1]
  1389. elif k[0] == "OVS_TUNNEL_KEY_ATTR_IPV6_SRC":
  1390. print_str += "ipv6_src=%s" % k[1]
  1391. elif k[0] == "OVS_TUNNEL_KEY_ATTR_IPV6_DST":
  1392. print_str += "ipv6_dst=%s" % k[1]
  1393. elif k[0] == "OVS_TUNNEL_KEY_ATTR_TOS":
  1394. print_str += "tos=%d" % k[1]
  1395. elif k[0] == "OVS_TUNNEL_KEY_ATTR_TTL":
  1396. print_str += "ttl=%d" % k[1]
  1397. elif k[0] == "OVS_TUNNEL_KEY_ATTR_TP_SRC":
  1398. print_str += "tp_src=%d" % k[1]
  1399. elif k[0] == "OVS_TUNNEL_KEY_ATTR_TP_DST":
  1400. print_str += "tp_dst=%d" % k[1]
  1401. elif k[0] == "OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT":
  1402. noprint = True
  1403. flagsattrs.append("df")
  1404. elif k[0] == "OVS_TUNNEL_KEY_ATTR_CSUM":
  1405. noprint = True
  1406. flagsattrs.append("csum")
  1407. elif k[0] == "OVS_TUNNEL_KEY_ATTR_OAM":
  1408. noprint = True
  1409. flagsattrs.append("oam")
  1410. if not noprint:
  1411. print_str += ","
  1412. if len(flagsattrs):
  1413. print_str += "flags(" + "|".join(flagsattrs) + ")"
  1414. print_str += ")"
  1415. return print_str
  1416. class ovs_key_mpls(nla):
  1417. fields = (("lse", ">I"),)
  1418. def parse(self, flowstr, mask=None):
  1419. for field in (
  1420. ("OVS_KEY_ATTR_PRIORITY", "skb_priority", intparse),
  1421. ("OVS_KEY_ATTR_SKB_MARK", "skb_mark", intparse),
  1422. ("OVS_KEY_ATTR_RECIRC_ID", "recirc_id", intparse),
  1423. ("OVS_KEY_ATTR_TUNNEL", "tunnel", ovskey.ovs_key_tunnel),
  1424. ("OVS_KEY_ATTR_DP_HASH", "dp_hash", intparse),
  1425. ("OVS_KEY_ATTR_CT_STATE", "ct_state", parse_ct_state),
  1426. ("OVS_KEY_ATTR_CT_ZONE", "ct_zone", intparse),
  1427. ("OVS_KEY_ATTR_CT_MARK", "ct_mark", intparse),
  1428. ("OVS_KEY_ATTR_IN_PORT", "in_port", intparse),
  1429. (
  1430. "OVS_KEY_ATTR_ETHERNET",
  1431. "eth",
  1432. ovskey.ethaddr,
  1433. ),
  1434. (
  1435. "OVS_KEY_ATTR_ETHERTYPE",
  1436. "eth_type",
  1437. lambda x: intparse(x, "0xffff"),
  1438. ),
  1439. (
  1440. "OVS_KEY_ATTR_IPV4",
  1441. "ipv4",
  1442. ovskey.ovs_key_ipv4,
  1443. ),
  1444. (
  1445. "OVS_KEY_ATTR_IPV6",
  1446. "ipv6",
  1447. ovskey.ovs_key_ipv6,
  1448. ),
  1449. (
  1450. "OVS_KEY_ATTR_ARP",
  1451. "arp",
  1452. ovskey.ovs_key_arp,
  1453. ),
  1454. (
  1455. "OVS_KEY_ATTR_TCP",
  1456. "tcp",
  1457. ovskey.ovs_key_tcp,
  1458. ),
  1459. (
  1460. "OVS_KEY_ATTR_UDP",
  1461. "udp",
  1462. ovskey.ovs_key_udp,
  1463. ),
  1464. (
  1465. "OVS_KEY_ATTR_ICMP",
  1466. "icmp",
  1467. ovskey.ovs_key_icmp,
  1468. ),
  1469. (
  1470. "OVS_KEY_ATTR_TCP_FLAGS",
  1471. "tcp_flags",
  1472. lambda x: parse_flags(x, None),
  1473. ),
  1474. ):
  1475. fld = field[1] + "("
  1476. if not flowstr.startswith(fld):
  1477. continue
  1478. if not isinstance(field[2], types.FunctionType):
  1479. nk = field[2]()
  1480. flowstr, k, m = nk.parse(flowstr, field[2])
  1481. else:
  1482. flowstr = flowstr[len(fld) :]
  1483. flowstr, k, m = field[2](flowstr)
  1484. if m and mask is not None:
  1485. mask["attrs"].append([field[0], m])
  1486. self["attrs"].append([field[0], k])
  1487. flowstr = flowstr[strspn(flowstr, "), ") :]
  1488. return flowstr
  1489. def dpstr(self, mask=None, more=False):
  1490. print_str = ""
  1491. for field in (
  1492. (
  1493. "OVS_KEY_ATTR_PRIORITY",
  1494. "skb_priority",
  1495. "%d",
  1496. lambda x: False,
  1497. True,
  1498. ),
  1499. (
  1500. "OVS_KEY_ATTR_SKB_MARK",
  1501. "skb_mark",
  1502. "%d",
  1503. lambda x: False,
  1504. True,
  1505. ),
  1506. (
  1507. "OVS_KEY_ATTR_RECIRC_ID",
  1508. "recirc_id",
  1509. "0x%08X",
  1510. lambda x: False,
  1511. True,
  1512. ),
  1513. (
  1514. "OVS_KEY_ATTR_DP_HASH",
  1515. "dp_hash",
  1516. "0x%08X",
  1517. lambda x: False,
  1518. True,
  1519. ),
  1520. (
  1521. "OVS_KEY_ATTR_TUNNEL",
  1522. "tunnel",
  1523. None,
  1524. False,
  1525. False,
  1526. ),
  1527. (
  1528. "OVS_KEY_ATTR_CT_STATE",
  1529. "ct_state",
  1530. "0x%04x",
  1531. lambda x: False,
  1532. True,
  1533. ),
  1534. (
  1535. "OVS_KEY_ATTR_CT_ZONE",
  1536. "ct_zone",
  1537. "0x%04x",
  1538. lambda x: False,
  1539. True,
  1540. ),
  1541. (
  1542. "OVS_KEY_ATTR_CT_MARK",
  1543. "ct_mark",
  1544. "0x%08x",
  1545. lambda x: False,
  1546. True,
  1547. ),
  1548. (
  1549. "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4",
  1550. None,
  1551. None,
  1552. False,
  1553. False,
  1554. ),
  1555. (
  1556. "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6",
  1557. None,
  1558. None,
  1559. False,
  1560. False,
  1561. ),
  1562. (
  1563. "OVS_KEY_ATTR_IN_PORT",
  1564. "in_port",
  1565. "%d",
  1566. lambda x: True,
  1567. True,
  1568. ),
  1569. ("OVS_KEY_ATTR_ETHERNET", None, None, False, False),
  1570. (
  1571. "OVS_KEY_ATTR_ETHERTYPE",
  1572. "eth_type",
  1573. "0x%04x",
  1574. lambda x: int(x) == 0xFFFF,
  1575. True,
  1576. ),
  1577. ("OVS_KEY_ATTR_IPV4", None, None, False, False),
  1578. ("OVS_KEY_ATTR_IPV6", None, None, False, False),
  1579. ("OVS_KEY_ATTR_ARP", None, None, False, False),
  1580. ("OVS_KEY_ATTR_TCP", None, None, False, False),
  1581. (
  1582. "OVS_KEY_ATTR_TCP_FLAGS",
  1583. "tcp_flags",
  1584. "0x%04x",
  1585. lambda x: False,
  1586. True,
  1587. ),
  1588. ("OVS_KEY_ATTR_UDP", None, None, False, False),
  1589. ("OVS_KEY_ATTR_SCTP", None, None, False, False),
  1590. ("OVS_KEY_ATTR_ICMP", None, None, False, False),
  1591. ("OVS_KEY_ATTR_ICMPV6", None, None, False, False),
  1592. ("OVS_KEY_ATTR_ND", None, None, False, False),
  1593. ):
  1594. v = self.get_attr(field[0])
  1595. if v is not None:
  1596. m = None if mask is None else mask.get_attr(field[0])
  1597. if field[4] is False:
  1598. print_str += v.dpstr(m, more)
  1599. print_str += ","
  1600. else:
  1601. if m is None or field[3](m):
  1602. print_str += field[1] + "("
  1603. print_str += field[2] % v
  1604. print_str += "),"
  1605. elif more or m != 0:
  1606. print_str += field[1] + "("
  1607. print_str += (field[2] % v) + "/" + (field[2] % m)
  1608. print_str += "),"
  1609. return print_str
  1610. class OvsPacket(GenericNetlinkSocket):
  1611. OVS_PACKET_CMD_MISS = 1 # Flow table miss
  1612. OVS_PACKET_CMD_ACTION = 2 # USERSPACE action
  1613. OVS_PACKET_CMD_EXECUTE = 3 # Apply actions to packet
  1614. class ovs_packet_msg(ovs_dp_msg):
  1615. nla_map = (
  1616. ("OVS_PACKET_ATTR_UNSPEC", "none"),
  1617. ("OVS_PACKET_ATTR_PACKET", "array(uint8)"),
  1618. ("OVS_PACKET_ATTR_KEY", "ovskey"),
  1619. ("OVS_PACKET_ATTR_ACTIONS", "ovsactions"),
  1620. ("OVS_PACKET_ATTR_USERDATA", "none"),
  1621. ("OVS_PACKET_ATTR_EGRESS_TUN_KEY", "none"),
  1622. ("OVS_PACKET_ATTR_UNUSED1", "none"),
  1623. ("OVS_PACKET_ATTR_UNUSED2", "none"),
  1624. ("OVS_PACKET_ATTR_PROBE", "none"),
  1625. ("OVS_PACKET_ATTR_MRU", "uint16"),
  1626. ("OVS_PACKET_ATTR_LEN", "uint32"),
  1627. ("OVS_PACKET_ATTR_HASH", "uint64"),
  1628. )
  1629. def __init__(self):
  1630. GenericNetlinkSocket.__init__(self)
  1631. self.bind(OVS_PACKET_FAMILY, OvsPacket.ovs_packet_msg)
  1632. def upcall_handler(self, up=None):
  1633. print("listening on upcall packet handler:", self.epid)
  1634. while True:
  1635. try:
  1636. msgs = self.get()
  1637. for msg in msgs:
  1638. if not up:
  1639. continue
  1640. if msg["cmd"] == OvsPacket.OVS_PACKET_CMD_MISS:
  1641. up.miss(msg)
  1642. elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_ACTION:
  1643. up.action(msg)
  1644. elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_EXECUTE:
  1645. up.execute(msg)
  1646. else:
  1647. print("Unkonwn cmd: %d" % msg["cmd"])
  1648. except NetlinkError as ne:
  1649. raise ne
  1650. class OvsDatapath(GenericNetlinkSocket):
  1651. OVS_DP_F_VPORT_PIDS = 1 << 1
  1652. OVS_DP_F_DISPATCH_UPCALL_PER_CPU = 1 << 3
  1653. class dp_cmd_msg(ovs_dp_msg):
  1654. """
  1655. Message class that will be used to communicate with the kernel module.
  1656. """
  1657. nla_map = (
  1658. ("OVS_DP_ATTR_UNSPEC", "none"),
  1659. ("OVS_DP_ATTR_NAME", "asciiz"),
  1660. ("OVS_DP_ATTR_UPCALL_PID", "array(uint32)"),
  1661. ("OVS_DP_ATTR_STATS", "dpstats"),
  1662. ("OVS_DP_ATTR_MEGAFLOW_STATS", "megaflowstats"),
  1663. ("OVS_DP_ATTR_USER_FEATURES", "uint32"),
  1664. ("OVS_DP_ATTR_PAD", "none"),
  1665. ("OVS_DP_ATTR_MASKS_CACHE_SIZE", "uint32"),
  1666. ("OVS_DP_ATTR_PER_CPU_PIDS", "array(uint32)"),
  1667. )
  1668. class dpstats(nla):
  1669. fields = (
  1670. ("hit", "=Q"),
  1671. ("missed", "=Q"),
  1672. ("lost", "=Q"),
  1673. ("flows", "=Q"),
  1674. )
  1675. class megaflowstats(nla):
  1676. fields = (
  1677. ("mask_hit", "=Q"),
  1678. ("masks", "=I"),
  1679. ("padding", "=I"),
  1680. ("cache_hits", "=Q"),
  1681. ("pad1", "=Q"),
  1682. )
  1683. def __init__(self):
  1684. GenericNetlinkSocket.__init__(self)
  1685. self.bind(OVS_DATAPATH_FAMILY, OvsDatapath.dp_cmd_msg)
  1686. def info(self, dpname, ifindex=0):
  1687. msg = OvsDatapath.dp_cmd_msg()
  1688. msg["cmd"] = OVS_DP_CMD_GET
  1689. msg["version"] = OVS_DATAPATH_VERSION
  1690. msg["reserved"] = 0
  1691. msg["dpifindex"] = ifindex
  1692. msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname])
  1693. try:
  1694. reply = self.nlm_request(
  1695. msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST
  1696. )
  1697. reply = reply[0]
  1698. except NetlinkError as ne:
  1699. if ne.code == errno.ENODEV:
  1700. reply = None
  1701. else:
  1702. raise ne
  1703. return reply
  1704. def create(
  1705. self, dpname, shouldUpcall=False, versionStr=None, p=OvsPacket()
  1706. ):
  1707. msg = OvsDatapath.dp_cmd_msg()
  1708. msg["cmd"] = OVS_DP_CMD_NEW
  1709. if versionStr is None:
  1710. msg["version"] = OVS_DATAPATH_VERSION
  1711. else:
  1712. msg["version"] = int(versionStr.split(":")[0], 0)
  1713. msg["reserved"] = 0
  1714. msg["dpifindex"] = 0
  1715. msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname])
  1716. dpfeatures = 0
  1717. if versionStr is not None and versionStr.find(":") != -1:
  1718. dpfeatures = int(versionStr.split(":")[1], 0)
  1719. else:
  1720. if versionStr is None or versionStr.find(":") == -1:
  1721. dpfeatures |= OvsDatapath.OVS_DP_F_DISPATCH_UPCALL_PER_CPU
  1722. dpfeatures &= ~OvsDatapath.OVS_DP_F_VPORT_PIDS
  1723. nproc = multiprocessing.cpu_count()
  1724. procarray = []
  1725. for i in range(1, nproc):
  1726. procarray += [int(p.epid)]
  1727. msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", procarray])
  1728. msg["attrs"].append(["OVS_DP_ATTR_USER_FEATURES", dpfeatures])
  1729. if not shouldUpcall:
  1730. msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", [0]])
  1731. try:
  1732. reply = self.nlm_request(
  1733. msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK
  1734. )
  1735. reply = reply[0]
  1736. except NetlinkError as ne:
  1737. if ne.code == errno.EEXIST:
  1738. reply = None
  1739. else:
  1740. raise ne
  1741. return reply
  1742. def destroy(self, dpname):
  1743. msg = OvsDatapath.dp_cmd_msg()
  1744. msg["cmd"] = OVS_DP_CMD_DEL
  1745. msg["version"] = OVS_DATAPATH_VERSION
  1746. msg["reserved"] = 0
  1747. msg["dpifindex"] = 0
  1748. msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname])
  1749. try:
  1750. reply = self.nlm_request(
  1751. msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK
  1752. )
  1753. reply = reply[0]
  1754. except NetlinkError as ne:
  1755. if ne.code == errno.ENODEV:
  1756. reply = None
  1757. else:
  1758. raise ne
  1759. return reply
  1760. class OvsVport(GenericNetlinkSocket):
  1761. OVS_VPORT_TYPE_NETDEV = 1
  1762. OVS_VPORT_TYPE_INTERNAL = 2
  1763. OVS_VPORT_TYPE_GRE = 3
  1764. OVS_VPORT_TYPE_VXLAN = 4
  1765. OVS_VPORT_TYPE_GENEVE = 5
  1766. class ovs_vport_msg(ovs_dp_msg):
  1767. nla_map = (
  1768. ("OVS_VPORT_ATTR_UNSPEC", "none"),
  1769. ("OVS_VPORT_ATTR_PORT_NO", "uint32"),
  1770. ("OVS_VPORT_ATTR_TYPE", "uint32"),
  1771. ("OVS_VPORT_ATTR_NAME", "asciiz"),
  1772. ("OVS_VPORT_ATTR_OPTIONS", "vportopts"),
  1773. ("OVS_VPORT_ATTR_UPCALL_PID", "array(uint32)"),
  1774. ("OVS_VPORT_ATTR_STATS", "vportstats"),
  1775. ("OVS_VPORT_ATTR_PAD", "none"),
  1776. ("OVS_VPORT_ATTR_IFINDEX", "uint32"),
  1777. ("OVS_VPORT_ATTR_NETNSID", "uint32"),
  1778. )
  1779. class vportopts(nla):
  1780. nla_map = (
  1781. ("OVS_TUNNEL_ATTR_UNSPEC", "none"),
  1782. ("OVS_TUNNEL_ATTR_DST_PORT", "uint16"),
  1783. ("OVS_TUNNEL_ATTR_EXTENSION", "none"),
  1784. )
  1785. class vportstats(nla):
  1786. fields = (
  1787. ("rx_packets", "=Q"),
  1788. ("tx_packets", "=Q"),
  1789. ("rx_bytes", "=Q"),
  1790. ("tx_bytes", "=Q"),
  1791. ("rx_errors", "=Q"),
  1792. ("tx_errors", "=Q"),
  1793. ("rx_dropped", "=Q"),
  1794. ("tx_dropped", "=Q"),
  1795. )
  1796. def type_to_str(vport_type):
  1797. if vport_type == OvsVport.OVS_VPORT_TYPE_NETDEV:
  1798. return "netdev"
  1799. elif vport_type == OvsVport.OVS_VPORT_TYPE_INTERNAL:
  1800. return "internal"
  1801. elif vport_type == OvsVport.OVS_VPORT_TYPE_GRE:
  1802. return "gre"
  1803. elif vport_type == OvsVport.OVS_VPORT_TYPE_VXLAN:
  1804. return "vxlan"
  1805. elif vport_type == OvsVport.OVS_VPORT_TYPE_GENEVE:
  1806. return "geneve"
  1807. raise ValueError("Unknown vport type:%d" % vport_type)
  1808. def str_to_type(vport_type):
  1809. if vport_type == "netdev":
  1810. return OvsVport.OVS_VPORT_TYPE_NETDEV
  1811. elif vport_type == "internal":
  1812. return OvsVport.OVS_VPORT_TYPE_INTERNAL
  1813. elif vport_type == "gre":
  1814. return OvsVport.OVS_VPORT_TYPE_INTERNAL
  1815. elif vport_type == "vxlan":
  1816. return OvsVport.OVS_VPORT_TYPE_VXLAN
  1817. elif vport_type == "geneve":
  1818. return OvsVport.OVS_VPORT_TYPE_GENEVE
  1819. raise ValueError("Unknown vport type: '%s'" % vport_type)
  1820. def __init__(self, packet=OvsPacket()):
  1821. GenericNetlinkSocket.__init__(self)
  1822. self.bind(OVS_VPORT_FAMILY, OvsVport.ovs_vport_msg)
  1823. self.upcall_packet = packet
  1824. def info(self, vport_name, dpifindex=0, portno=None):
  1825. msg = OvsVport.ovs_vport_msg()
  1826. msg["cmd"] = OVS_VPORT_CMD_GET
  1827. msg["version"] = OVS_DATAPATH_VERSION
  1828. msg["reserved"] = 0
  1829. msg["dpifindex"] = dpifindex
  1830. if portno is None:
  1831. msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_name])
  1832. else:
  1833. msg["attrs"].append(["OVS_VPORT_ATTR_PORT_NO", portno])
  1834. try:
  1835. reply = self.nlm_request(
  1836. msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST
  1837. )
  1838. reply = reply[0]
  1839. except NetlinkError as ne:
  1840. if ne.code == errno.ENODEV:
  1841. reply = None
  1842. else:
  1843. raise ne
  1844. return reply
  1845. def attach(self, dpindex, vport_ifname, ptype, dport, lwt):
  1846. msg = OvsVport.ovs_vport_msg()
  1847. msg["cmd"] = OVS_VPORT_CMD_NEW
  1848. msg["version"] = OVS_DATAPATH_VERSION
  1849. msg["reserved"] = 0
  1850. msg["dpifindex"] = dpindex
  1851. port_type = OvsVport.str_to_type(ptype)
  1852. msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname])
  1853. msg["attrs"].append(
  1854. ["OVS_VPORT_ATTR_UPCALL_PID", [self.upcall_packet.epid]]
  1855. )
  1856. TUNNEL_DEFAULTS = [("geneve", 6081),
  1857. ("vxlan", 4789)]
  1858. for tnl in TUNNEL_DEFAULTS:
  1859. if ptype == tnl[0]:
  1860. if not dport:
  1861. dport = tnl[1]
  1862. if not lwt:
  1863. vportopt = OvsVport.ovs_vport_msg.vportopts()
  1864. vportopt["attrs"].append(
  1865. ["OVS_TUNNEL_ATTR_DST_PORT", socket.htons(dport)]
  1866. )
  1867. msg["attrs"].append(
  1868. ["OVS_VPORT_ATTR_OPTIONS", vportopt]
  1869. )
  1870. else:
  1871. port_type = OvsVport.OVS_VPORT_TYPE_NETDEV
  1872. ipr = pyroute2.iproute.IPRoute()
  1873. if tnl[0] == "geneve":
  1874. ipr.link("add", ifname=vport_ifname, kind=tnl[0],
  1875. geneve_port=dport,
  1876. geneve_collect_metadata=True,
  1877. geneve_udp_zero_csum6_rx=1)
  1878. elif tnl[0] == "vxlan":
  1879. ipr.link("add", ifname=vport_ifname, kind=tnl[0],
  1880. vxlan_learning=0, vxlan_collect_metadata=1,
  1881. vxlan_udp_zero_csum6_rx=1, vxlan_port=dport)
  1882. break
  1883. msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type])
  1884. try:
  1885. reply = self.nlm_request(
  1886. msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK
  1887. )
  1888. reply = reply[0]
  1889. except NetlinkError as ne:
  1890. if ne.code == errno.EEXIST:
  1891. reply = None
  1892. else:
  1893. raise ne
  1894. return reply
  1895. def reset_upcall(self, dpindex, vport_ifname, p=None):
  1896. msg = OvsVport.ovs_vport_msg()
  1897. msg["cmd"] = OVS_VPORT_CMD_SET
  1898. msg["version"] = OVS_DATAPATH_VERSION
  1899. msg["reserved"] = 0
  1900. msg["dpifindex"] = dpindex
  1901. msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname])
  1902. if p == None:
  1903. p = self.upcall_packet
  1904. else:
  1905. self.upcall_packet = p
  1906. msg["attrs"].append(["OVS_VPORT_ATTR_UPCALL_PID", [p.epid]])
  1907. try:
  1908. reply = self.nlm_request(
  1909. msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK
  1910. )
  1911. reply = reply[0]
  1912. except NetlinkError as ne:
  1913. raise ne
  1914. return reply
  1915. def detach(self, dpindex, vport_ifname):
  1916. msg = OvsVport.ovs_vport_msg()
  1917. msg["cmd"] = OVS_VPORT_CMD_DEL
  1918. msg["version"] = OVS_DATAPATH_VERSION
  1919. msg["reserved"] = 0
  1920. msg["dpifindex"] = dpindex
  1921. msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname])
  1922. try:
  1923. reply = self.nlm_request(
  1924. msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK
  1925. )
  1926. reply = reply[0]
  1927. except NetlinkError as ne:
  1928. if ne.code == errno.ENODEV:
  1929. reply = None
  1930. else:
  1931. raise ne
  1932. return reply
  1933. def upcall_handler(self, handler=None):
  1934. self.upcall_packet.upcall_handler(handler)
  1935. class OvsFlow(GenericNetlinkSocket):
  1936. class ovs_flow_msg(ovs_dp_msg):
  1937. nla_map = (
  1938. ("OVS_FLOW_ATTR_UNSPEC", "none"),
  1939. ("OVS_FLOW_ATTR_KEY", "ovskey"),
  1940. ("OVS_FLOW_ATTR_ACTIONS", "ovsactions"),
  1941. ("OVS_FLOW_ATTR_STATS", "flowstats"),
  1942. ("OVS_FLOW_ATTR_TCP_FLAGS", "uint8"),
  1943. ("OVS_FLOW_ATTR_USED", "uint64"),
  1944. ("OVS_FLOW_ATTR_CLEAR", "none"),
  1945. ("OVS_FLOW_ATTR_MASK", "ovskey"),
  1946. ("OVS_FLOW_ATTR_PROBE", "none"),
  1947. ("OVS_FLOW_ATTR_UFID", "array(uint32)"),
  1948. ("OVS_FLOW_ATTR_UFID_FLAGS", "uint32"),
  1949. )
  1950. class flowstats(nla):
  1951. fields = (
  1952. ("packets", "=Q"),
  1953. ("bytes", "=Q"),
  1954. )
  1955. def dpstr(self, more=False):
  1956. ufid = self.get_attr("OVS_FLOW_ATTR_UFID")
  1957. ufid_str = ""
  1958. if ufid is not None:
  1959. ufid_str = (
  1960. "ufid:{:08x}-{:04x}-{:04x}-{:04x}-{:04x}{:08x}".format(
  1961. ufid[0],
  1962. ufid[1] >> 16,
  1963. ufid[1] & 0xFFFF,
  1964. ufid[2] >> 16,
  1965. ufid[2] & 0,
  1966. ufid[3],
  1967. )
  1968. )
  1969. key_field = self.get_attr("OVS_FLOW_ATTR_KEY")
  1970. keymsg = None
  1971. if key_field is not None:
  1972. keymsg = key_field
  1973. mask_field = self.get_attr("OVS_FLOW_ATTR_MASK")
  1974. maskmsg = None
  1975. if mask_field is not None:
  1976. maskmsg = mask_field
  1977. acts_field = self.get_attr("OVS_FLOW_ATTR_ACTIONS")
  1978. actsmsg = None
  1979. if acts_field is not None:
  1980. actsmsg = acts_field
  1981. print_str = ""
  1982. if more:
  1983. print_str += ufid_str + ","
  1984. if keymsg is not None:
  1985. print_str += keymsg.dpstr(maskmsg, more)
  1986. stats = self.get_attr("OVS_FLOW_ATTR_STATS")
  1987. if stats is None:
  1988. print_str += " packets:0, bytes:0,"
  1989. else:
  1990. print_str += " packets:%d, bytes:%d," % (
  1991. stats["packets"],
  1992. stats["bytes"],
  1993. )
  1994. used = self.get_attr("OVS_FLOW_ATTR_USED")
  1995. print_str += " used:"
  1996. if used is None:
  1997. print_str += "never,"
  1998. else:
  1999. used_time = int(used)
  2000. cur_time_sec = time.clock_gettime(time.CLOCK_MONOTONIC)
  2001. used_time = (cur_time_sec * 1000) - used_time
  2002. print_str += "{}s,".format(used_time / 1000)
  2003. print_str += " actions:"
  2004. if (
  2005. actsmsg is None
  2006. or "attrs" not in actsmsg
  2007. or len(actsmsg["attrs"]) == 0
  2008. ):
  2009. print_str += "drop"
  2010. else:
  2011. print_str += actsmsg.dpstr(more)
  2012. return print_str
  2013. def parse(self, flowstr, actstr, dpidx=0):
  2014. OVS_UFID_F_OMIT_KEY = 1 << 0
  2015. OVS_UFID_F_OMIT_MASK = 1 << 1
  2016. OVS_UFID_F_OMIT_ACTIONS = 1 << 2
  2017. self["cmd"] = 0
  2018. self["version"] = 0
  2019. self["reserved"] = 0
  2020. self["dpifindex"] = 0
  2021. if flowstr.startswith("ufid:"):
  2022. count = 5
  2023. while flowstr[count] != ",":
  2024. count += 1
  2025. ufidstr = flowstr[5:count]
  2026. flowstr = flowstr[count + 1 :]
  2027. else:
  2028. ufidstr = str(uuid.uuid4())
  2029. uuidRawObj = uuid.UUID(ufidstr).fields
  2030. self["attrs"].append(
  2031. [
  2032. "OVS_FLOW_ATTR_UFID",
  2033. [
  2034. uuidRawObj[0],
  2035. uuidRawObj[1] << 16 | uuidRawObj[2],
  2036. uuidRawObj[3] << 24
  2037. | uuidRawObj[4] << 16
  2038. | uuidRawObj[5] & (0xFF << 32) >> 32,
  2039. uuidRawObj[5] & (0xFFFFFFFF),
  2040. ],
  2041. ]
  2042. )
  2043. self["attrs"].append(
  2044. [
  2045. "OVS_FLOW_ATTR_UFID_FLAGS",
  2046. int(
  2047. OVS_UFID_F_OMIT_KEY
  2048. | OVS_UFID_F_OMIT_MASK
  2049. | OVS_UFID_F_OMIT_ACTIONS
  2050. ),
  2051. ]
  2052. )
  2053. k = ovskey()
  2054. m = ovskey()
  2055. k.parse(flowstr, m)
  2056. self["attrs"].append(["OVS_FLOW_ATTR_KEY", k])
  2057. self["attrs"].append(["OVS_FLOW_ATTR_MASK", m])
  2058. a = ovsactions()
  2059. a.parse(actstr)
  2060. self["attrs"].append(["OVS_FLOW_ATTR_ACTIONS", a])
  2061. def __init__(self):
  2062. GenericNetlinkSocket.__init__(self)
  2063. self.bind(OVS_FLOW_FAMILY, OvsFlow.ovs_flow_msg)
  2064. def add_flow(self, dpifindex, flowmsg):
  2065. """
  2066. Send a new flow message to the kernel.
  2067. dpifindex should be a valid datapath obtained by calling
  2068. into the OvsDatapath lookup
  2069. flowmsg is a flow object obtained by calling a dpparse
  2070. """
  2071. flowmsg["cmd"] = OVS_FLOW_CMD_NEW
  2072. flowmsg["version"] = OVS_DATAPATH_VERSION
  2073. flowmsg["reserved"] = 0
  2074. flowmsg["dpifindex"] = dpifindex
  2075. try:
  2076. reply = self.nlm_request(
  2077. flowmsg,
  2078. msg_type=self.prid,
  2079. msg_flags=NLM_F_REQUEST | NLM_F_ACK,
  2080. )
  2081. reply = reply[0]
  2082. except NetlinkError as ne:
  2083. print(flowmsg)
  2084. raise ne
  2085. return reply
  2086. def del_flows(self, dpifindex):
  2087. """
  2088. Send a del message to the kernel that will drop all flows.
  2089. dpifindex should be a valid datapath obtained by calling
  2090. into the OvsDatapath lookup
  2091. """
  2092. flowmsg = OvsFlow.ovs_flow_msg()
  2093. flowmsg["cmd"] = OVS_FLOW_CMD_DEL
  2094. flowmsg["version"] = OVS_DATAPATH_VERSION
  2095. flowmsg["reserved"] = 0
  2096. flowmsg["dpifindex"] = dpifindex
  2097. try:
  2098. reply = self.nlm_request(
  2099. flowmsg,
  2100. msg_type=self.prid,
  2101. msg_flags=NLM_F_REQUEST | NLM_F_ACK,
  2102. )
  2103. reply = reply[0]
  2104. except NetlinkError as ne:
  2105. print(flowmsg)
  2106. raise ne
  2107. return reply
  2108. def dump(self, dpifindex, flowspec=None):
  2109. """
  2110. Returns a list of messages containing flows.
  2111. dpifindex should be a valid datapath obtained by calling
  2112. into the OvsDatapath lookup
  2113. flowpsec is a string which represents a flow in the dpctl
  2114. format.
  2115. """
  2116. msg = OvsFlow.ovs_flow_msg()
  2117. msg["cmd"] = OVS_FLOW_CMD_GET
  2118. msg["version"] = OVS_DATAPATH_VERSION
  2119. msg["reserved"] = 0
  2120. msg["dpifindex"] = dpifindex
  2121. msg_flags = NLM_F_REQUEST | NLM_F_ACK
  2122. if flowspec is None:
  2123. msg_flags |= NLM_F_DUMP
  2124. rep = None
  2125. try:
  2126. rep = self.nlm_request(
  2127. msg,
  2128. msg_type=self.prid,
  2129. msg_flags=msg_flags,
  2130. )
  2131. except NetlinkError as ne:
  2132. raise ne
  2133. return rep
  2134. def miss(self, packetmsg):
  2135. seq = packetmsg["header"]["sequence_number"]
  2136. keystr = "(none)"
  2137. key_field = packetmsg.get_attr("OVS_PACKET_ATTR_KEY")
  2138. if key_field is not None:
  2139. keystr = key_field.dpstr(None, True)
  2140. pktdata = packetmsg.get_attr("OVS_PACKET_ATTR_PACKET")
  2141. pktpres = "yes" if pktdata is not None else "no"
  2142. print("MISS upcall[%d/%s]: %s" % (seq, pktpres, keystr), flush=True)
  2143. def execute(self, packetmsg):
  2144. print("userspace execute command", flush=True)
  2145. def action(self, packetmsg):
  2146. print("userspace action command", flush=True)
  2147. class psample_sample(genlmsg):
  2148. nla_map = (
  2149. ("PSAMPLE_ATTR_IIFINDEX", "none"),
  2150. ("PSAMPLE_ATTR_OIFINDEX", "none"),
  2151. ("PSAMPLE_ATTR_ORIGSIZE", "none"),
  2152. ("PSAMPLE_ATTR_SAMPLE_GROUP", "uint32"),
  2153. ("PSAMPLE_ATTR_GROUP_SEQ", "none"),
  2154. ("PSAMPLE_ATTR_SAMPLE_RATE", "uint32"),
  2155. ("PSAMPLE_ATTR_DATA", "array(uint8)"),
  2156. ("PSAMPLE_ATTR_GROUP_REFCOUNT", "none"),
  2157. ("PSAMPLE_ATTR_TUNNEL", "none"),
  2158. ("PSAMPLE_ATTR_PAD", "none"),
  2159. ("PSAMPLE_ATTR_OUT_TC", "none"),
  2160. ("PSAMPLE_ATTR_OUT_TC_OCC", "none"),
  2161. ("PSAMPLE_ATTR_LATENCY", "none"),
  2162. ("PSAMPLE_ATTR_TIMESTAMP", "none"),
  2163. ("PSAMPLE_ATTR_PROTO", "none"),
  2164. ("PSAMPLE_ATTR_USER_COOKIE", "array(uint8)"),
  2165. )
  2166. def dpstr(self):
  2167. fields = []
  2168. data = ""
  2169. for (attr, value) in self["attrs"]:
  2170. if attr == "PSAMPLE_ATTR_SAMPLE_GROUP":
  2171. fields.append("group:%d" % value)
  2172. if attr == "PSAMPLE_ATTR_SAMPLE_RATE":
  2173. fields.append("rate:%d" % value)
  2174. if attr == "PSAMPLE_ATTR_USER_COOKIE":
  2175. value = "".join(format(x, "02x") for x in value)
  2176. fields.append("cookie:%s" % value)
  2177. if attr == "PSAMPLE_ATTR_DATA" and len(value) > 0:
  2178. data = "data:%s" % "".join(format(x, "02x") for x in value)
  2179. return ("%s %s" % (",".join(fields), data)).strip()
  2180. class psample_msg(Marshal):
  2181. PSAMPLE_CMD_SAMPLE = 0
  2182. PSAMPLE_CMD_GET_GROUP = 1
  2183. PSAMPLE_CMD_NEW_GROUP = 2
  2184. PSAMPLE_CMD_DEL_GROUP = 3
  2185. PSAMPLE_CMD_SET_FILTER = 4
  2186. msg_map = {PSAMPLE_CMD_SAMPLE: psample_sample}
  2187. class PsampleEvent(EventSocket):
  2188. genl_family = "psample"
  2189. mcast_groups = ["packets"]
  2190. marshal_class = psample_msg
  2191. def read_samples(self):
  2192. print("listening for psample events", flush=True)
  2193. while True:
  2194. try:
  2195. for msg in self.get():
  2196. print(msg.dpstr(), flush=True)
  2197. except NetlinkError as ne:
  2198. raise ne
  2199. def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()):
  2200. dp_name = dp_lookup_rep.get_attr("OVS_DP_ATTR_NAME")
  2201. base_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_STATS")
  2202. megaflow_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_MEGAFLOW_STATS")
  2203. user_features = dp_lookup_rep.get_attr("OVS_DP_ATTR_USER_FEATURES")
  2204. masks_cache_size = dp_lookup_rep.get_attr("OVS_DP_ATTR_MASKS_CACHE_SIZE")
  2205. print("%s:" % dp_name)
  2206. print(
  2207. " lookups: hit:%d missed:%d lost:%d"
  2208. % (base_stats["hit"], base_stats["missed"], base_stats["lost"])
  2209. )
  2210. print(" flows:%d" % base_stats["flows"])
  2211. pkts = base_stats["hit"] + base_stats["missed"]
  2212. avg = (megaflow_stats["mask_hit"] / pkts) if pkts != 0 else 0.0
  2213. print(
  2214. " masks: hit:%d total:%d hit/pkt:%f"
  2215. % (megaflow_stats["mask_hit"], megaflow_stats["masks"], avg)
  2216. )
  2217. print(" caches:")
  2218. print(" masks-cache: size:%d" % masks_cache_size)
  2219. if user_features is not None:
  2220. print(" features: 0x%X" % user_features)
  2221. # port print out
  2222. for iface in ndb.interfaces:
  2223. rep = vpl.info(iface.ifname, ifindex)
  2224. if rep is not None:
  2225. opts = ""
  2226. vpo = rep.get_attr("OVS_VPORT_ATTR_OPTIONS")
  2227. if vpo:
  2228. dpo = vpo.get_attr("OVS_TUNNEL_ATTR_DST_PORT")
  2229. if dpo:
  2230. opts += " tnl-dport:%s" % socket.ntohs(dpo)
  2231. print(
  2232. " port %d: %s (%s%s)"
  2233. % (
  2234. rep.get_attr("OVS_VPORT_ATTR_PORT_NO"),
  2235. rep.get_attr("OVS_VPORT_ATTR_NAME"),
  2236. OvsVport.type_to_str(rep.get_attr("OVS_VPORT_ATTR_TYPE")),
  2237. opts,
  2238. )
  2239. )
  2240. def main(argv):
  2241. nlmsg_atoms.ovskey = ovskey
  2242. nlmsg_atoms.ovsactions = ovsactions
  2243. # version check for pyroute2
  2244. prverscheck = pyroute2.__version__.split(".")
  2245. if int(prverscheck[0]) == 0 and int(prverscheck[1]) < 6:
  2246. print("Need to upgrade the python pyroute2 package to >= 0.6.")
  2247. sys.exit(0)
  2248. parser = argparse.ArgumentParser()
  2249. parser.add_argument(
  2250. "-v",
  2251. "--verbose",
  2252. action="count",
  2253. help="Increment 'verbose' output counter.",
  2254. default=0,
  2255. )
  2256. subparsers = parser.add_subparsers(dest="subcommand")
  2257. showdpcmd = subparsers.add_parser("show")
  2258. showdpcmd.add_argument(
  2259. "showdp", metavar="N", type=str, nargs="?", help="Datapath Name"
  2260. )
  2261. adddpcmd = subparsers.add_parser("add-dp")
  2262. adddpcmd.add_argument("adddp", help="Datapath Name")
  2263. adddpcmd.add_argument(
  2264. "-u",
  2265. "--upcall",
  2266. action="store_true",
  2267. help="Leave open a reader for upcalls",
  2268. )
  2269. adddpcmd.add_argument(
  2270. "-V",
  2271. "--versioning",
  2272. required=False,
  2273. help="Specify a custom version / feature string",
  2274. )
  2275. deldpcmd = subparsers.add_parser("del-dp")
  2276. deldpcmd.add_argument("deldp", help="Datapath Name")
  2277. addifcmd = subparsers.add_parser("add-if")
  2278. addifcmd.add_argument("dpname", help="Datapath Name")
  2279. addifcmd.add_argument("addif", help="Interface name for adding")
  2280. addifcmd.add_argument(
  2281. "-u",
  2282. "--upcall",
  2283. action="store_true",
  2284. help="Leave open a reader for upcalls",
  2285. )
  2286. addifcmd.add_argument(
  2287. "-t",
  2288. "--ptype",
  2289. type=str,
  2290. default="netdev",
  2291. choices=["netdev", "internal", "geneve", "vxlan"],
  2292. help="Interface type (default netdev)",
  2293. )
  2294. addifcmd.add_argument(
  2295. "-p",
  2296. "--dport",
  2297. type=int,
  2298. default=0,
  2299. help="Destination port (0 for default)"
  2300. )
  2301. addifcmd.add_argument(
  2302. "-l",
  2303. "--lwt",
  2304. type=bool,
  2305. default=True,
  2306. help="Use LWT infrastructure instead of vport (default true)."
  2307. )
  2308. delifcmd = subparsers.add_parser("del-if")
  2309. delifcmd.add_argument("dpname", help="Datapath Name")
  2310. delifcmd.add_argument("delif", help="Interface name for adding")
  2311. delifcmd.add_argument("-d",
  2312. "--dellink",
  2313. type=bool, default=False,
  2314. help="Delete the link as well.")
  2315. dumpflcmd = subparsers.add_parser("dump-flows")
  2316. dumpflcmd.add_argument("dumpdp", help="Datapath Name")
  2317. addflcmd = subparsers.add_parser("add-flow")
  2318. addflcmd.add_argument("flbr", help="Datapath name")
  2319. addflcmd.add_argument("flow", help="Flow specification")
  2320. addflcmd.add_argument("acts", help="Flow actions")
  2321. delfscmd = subparsers.add_parser("del-flows")
  2322. delfscmd.add_argument("flsbr", help="Datapath name")
  2323. subparsers.add_parser("psample-events")
  2324. args = parser.parse_args()
  2325. if args.verbose > 0:
  2326. if args.verbose > 1:
  2327. logging.basicConfig(level=logging.DEBUG)
  2328. ovspk = OvsPacket()
  2329. ovsdp = OvsDatapath()
  2330. ovsvp = OvsVport(ovspk)
  2331. ovsflow = OvsFlow()
  2332. ndb = NDB()
  2333. sys.setrecursionlimit(100000)
  2334. if args.subcommand == "psample-events":
  2335. PsampleEvent().read_samples()
  2336. if hasattr(args, "showdp"):
  2337. found = False
  2338. for iface in ndb.interfaces:
  2339. rep = None
  2340. if args.showdp is None:
  2341. rep = ovsdp.info(iface.ifname, 0)
  2342. elif args.showdp == iface.ifname:
  2343. rep = ovsdp.info(iface.ifname, 0)
  2344. if rep is not None:
  2345. found = True
  2346. print_ovsdp_full(rep, iface.index, ndb, ovsvp)
  2347. if not found:
  2348. msg = "No DP found"
  2349. if args.showdp is not None:
  2350. msg += ":'%s'" % args.showdp
  2351. print(msg)
  2352. elif hasattr(args, "adddp"):
  2353. rep = ovsdp.create(args.adddp, args.upcall, args.versioning, ovspk)
  2354. if rep is None:
  2355. print("DP '%s' already exists" % args.adddp)
  2356. else:
  2357. print("DP '%s' added" % args.adddp)
  2358. if args.upcall:
  2359. ovspk.upcall_handler(ovsflow)
  2360. elif hasattr(args, "deldp"):
  2361. ovsdp.destroy(args.deldp)
  2362. elif hasattr(args, "addif"):
  2363. rep = ovsdp.info(args.dpname, 0)
  2364. if rep is None:
  2365. print("DP '%s' not found." % args.dpname)
  2366. return 1
  2367. dpindex = rep["dpifindex"]
  2368. rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype,
  2369. args.dport, args.lwt)
  2370. msg = "vport '%s'" % args.addif
  2371. if rep and rep["header"]["error"] is None:
  2372. msg += " added."
  2373. else:
  2374. msg += " failed to add."
  2375. if args.upcall:
  2376. if rep is None:
  2377. rep = ovsvp.reset_upcall(dpindex, args.addif, ovspk)
  2378. ovsvp.upcall_handler(ovsflow)
  2379. elif hasattr(args, "delif"):
  2380. rep = ovsdp.info(args.dpname, 0)
  2381. if rep is None:
  2382. print("DP '%s' not found." % args.dpname)
  2383. return 1
  2384. rep = ovsvp.detach(rep["dpifindex"], args.delif)
  2385. msg = "vport '%s'" % args.delif
  2386. if rep and rep["header"]["error"] is None:
  2387. msg += " removed."
  2388. else:
  2389. msg += " failed to remove."
  2390. if args.dellink:
  2391. ipr = pyroute2.iproute.IPRoute()
  2392. ipr.link("del", index=ipr.link_lookup(ifname=args.delif)[0])
  2393. elif hasattr(args, "dumpdp"):
  2394. rep = ovsdp.info(args.dumpdp, 0)
  2395. if rep is None:
  2396. print("DP '%s' not found." % args.dumpdp)
  2397. return 1
  2398. rep = ovsflow.dump(rep["dpifindex"])
  2399. for flow in rep:
  2400. print(flow.dpstr(True if args.verbose > 0 else False))
  2401. elif hasattr(args, "flbr"):
  2402. rep = ovsdp.info(args.flbr, 0)
  2403. if rep is None:
  2404. print("DP '%s' not found." % args.flbr)
  2405. return 1
  2406. flow = OvsFlow.ovs_flow_msg()
  2407. flow.parse(args.flow, args.acts, rep["dpifindex"])
  2408. ovsflow.add_flow(rep["dpifindex"], flow)
  2409. elif hasattr(args, "flsbr"):
  2410. rep = ovsdp.info(args.flsbr, 0)
  2411. if rep is None:
  2412. print("DP '%s' not found." % args.flsbr)
  2413. ovsflow.del_flows(rep["dpifindex"])
  2414. return 0
  2415. if __name__ == "__main__":
  2416. sys.exit(main(sys.argv))