u32.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. /*
  2. * lib/route/cls/u32.c u32 classifier
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation version 2.1
  7. * of the License.
  8. *
  9. * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
  10. * Copyright (c) 2005-2006 Petr Gotthard <petr.gotthard@siemens.com>
  11. * Copyright (c) 2005-2006 Siemens AG Oesterreich
  12. */
  13. /**
  14. * @ingroup cls
  15. * @defgroup cls_u32 Universal 32-bit Classifier
  16. *
  17. * @{
  18. */
  19. #include <netlink-private/netlink.h>
  20. #include <netlink-private/tc.h>
  21. #include <netlink/netlink.h>
  22. #include <netlink/attr.h>
  23. #include <netlink/utils.h>
  24. #include <netlink-private/route/tc-api.h>
  25. #include <netlink/route/classifier.h>
  26. #include <netlink/route/cls/u32.h>
  27. #include <netlink/route/action.h>
  28. /** @cond SKIP */
  29. #define U32_ATTR_DIVISOR 0x001
  30. #define U32_ATTR_HASH 0x002
  31. #define U32_ATTR_CLASSID 0x004
  32. #define U32_ATTR_LINK 0x008
  33. #define U32_ATTR_PCNT 0x010
  34. #define U32_ATTR_SELECTOR 0x020
  35. #define U32_ATTR_ACTION 0x040
  36. #define U32_ATTR_POLICE 0x080
  37. #define U32_ATTR_INDEV 0x100
  38. /** @endcond */
  39. static inline struct tc_u32_sel *u32_selector(struct rtnl_u32 *u)
  40. {
  41. return (struct tc_u32_sel *) u->cu_selector->d_data;
  42. }
  43. static inline struct tc_u32_sel *u32_selector_alloc(struct rtnl_u32 *u)
  44. {
  45. if (!u->cu_selector)
  46. u->cu_selector = nl_data_alloc(NULL, sizeof(struct tc_u32_sel));
  47. return u32_selector(u);
  48. }
  49. static struct nla_policy u32_policy[TCA_U32_MAX+1] = {
  50. [TCA_U32_DIVISOR] = { .type = NLA_U32 },
  51. [TCA_U32_HASH] = { .type = NLA_U32 },
  52. [TCA_U32_CLASSID] = { .type = NLA_U32 },
  53. [TCA_U32_LINK] = { .type = NLA_U32 },
  54. [TCA_U32_INDEV] = { .type = NLA_STRING,
  55. .maxlen = IFNAMSIZ },
  56. [TCA_U32_SEL] = { .minlen = sizeof(struct tc_u32_sel) },
  57. [TCA_U32_PCNT] = { .minlen = sizeof(struct tc_u32_pcnt) },
  58. };
  59. static int u32_msg_parser(struct rtnl_tc *tc, void *data)
  60. {
  61. struct rtnl_u32 *u = data;
  62. struct nlattr *tb[TCA_U32_MAX + 1];
  63. int err;
  64. err = tca_parse(tb, TCA_U32_MAX, tc, u32_policy);
  65. if (err < 0)
  66. return err;
  67. if (tb[TCA_U32_DIVISOR]) {
  68. u->cu_divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
  69. u->cu_mask |= U32_ATTR_DIVISOR;
  70. }
  71. if (tb[TCA_U32_SEL]) {
  72. u->cu_selector = nl_data_alloc_attr(tb[TCA_U32_SEL]);
  73. if (!u->cu_selector)
  74. goto errout_nomem;
  75. u->cu_mask |= U32_ATTR_SELECTOR;
  76. }
  77. if (tb[TCA_U32_HASH]) {
  78. u->cu_hash = nla_get_u32(tb[TCA_U32_HASH]);
  79. u->cu_mask |= U32_ATTR_HASH;
  80. }
  81. if (tb[TCA_U32_CLASSID]) {
  82. u->cu_classid = nla_get_u32(tb[TCA_U32_CLASSID]);
  83. u->cu_mask |= U32_ATTR_CLASSID;
  84. }
  85. if (tb[TCA_U32_LINK]) {
  86. u->cu_link = nla_get_u32(tb[TCA_U32_LINK]);
  87. u->cu_mask |= U32_ATTR_LINK;
  88. }
  89. if (tb[TCA_U32_ACT]) {
  90. u->cu_mask |= U32_ATTR_ACTION;
  91. err = rtnl_act_parse(&u->cu_act, tb[TCA_U32_ACT]);
  92. if (err)
  93. return err;
  94. }
  95. if (tb[TCA_U32_POLICE]) {
  96. u->cu_police = nl_data_alloc_attr(tb[TCA_U32_POLICE]);
  97. if (!u->cu_police)
  98. goto errout_nomem;
  99. u->cu_mask |= U32_ATTR_POLICE;
  100. }
  101. if (tb[TCA_U32_PCNT]) {
  102. struct tc_u32_sel *sel;
  103. size_t pcnt_size;
  104. if (!tb[TCA_U32_SEL]) {
  105. err = -NLE_MISSING_ATTR;
  106. goto errout;
  107. }
  108. sel = u->cu_selector->d_data;
  109. pcnt_size = sizeof(struct tc_u32_pcnt) +
  110. (sel->nkeys * sizeof(uint64_t));
  111. if (nla_len(tb[TCA_U32_PCNT]) < pcnt_size) {
  112. err = -NLE_INVAL;
  113. goto errout;
  114. }
  115. u->cu_pcnt = nl_data_alloc_attr(tb[TCA_U32_PCNT]);
  116. if (!u->cu_pcnt)
  117. goto errout_nomem;
  118. u->cu_mask |= U32_ATTR_PCNT;
  119. }
  120. if (tb[TCA_U32_INDEV]) {
  121. nla_strlcpy(u->cu_indev, tb[TCA_U32_INDEV], IFNAMSIZ);
  122. u->cu_mask |= U32_ATTR_INDEV;
  123. }
  124. return 0;
  125. errout_nomem:
  126. err = -NLE_NOMEM;
  127. errout:
  128. return err;
  129. }
  130. static void u32_free_data(struct rtnl_tc *tc, void *data)
  131. {
  132. struct rtnl_u32 *u = data;
  133. if (u->cu_act)
  134. rtnl_act_put_all(&u->cu_act);
  135. nl_data_free(u->cu_selector);
  136. nl_data_free(u->cu_police);
  137. nl_data_free(u->cu_pcnt);
  138. }
  139. static int u32_clone(void *_dst, void *_src)
  140. {
  141. struct rtnl_u32 *dst = _dst, *src = _src;
  142. if (src->cu_selector &&
  143. !(dst->cu_selector = nl_data_clone(src->cu_selector)))
  144. return -NLE_NOMEM;
  145. if (src->cu_act) {
  146. if (!(dst->cu_act = rtnl_act_alloc()))
  147. return -NLE_NOMEM;
  148. memcpy(dst->cu_act, src->cu_act, sizeof(struct rtnl_act));
  149. }
  150. if (src->cu_police && !(dst->cu_police = nl_data_clone(src->cu_police)))
  151. return -NLE_NOMEM;
  152. if (src->cu_pcnt && !(dst->cu_pcnt = nl_data_clone(src->cu_pcnt)))
  153. return -NLE_NOMEM;
  154. return 0;
  155. }
  156. static void u32_dump_line(struct rtnl_tc *tc, void *data,
  157. struct nl_dump_params *p)
  158. {
  159. struct rtnl_u32 *u = data;
  160. char buf[32];
  161. if (!u)
  162. return;
  163. if (u->cu_mask & U32_ATTR_DIVISOR)
  164. nl_dump(p, " divisor %u", u->cu_divisor);
  165. else if (u->cu_mask & U32_ATTR_CLASSID)
  166. nl_dump(p, " target %s",
  167. rtnl_tc_handle2str(u->cu_classid, buf, sizeof(buf)));
  168. }
  169. static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel,
  170. struct rtnl_u32 *u)
  171. {
  172. int i;
  173. struct tc_u32_key *key;
  174. if (sel->hmask || sel->hoff) {
  175. /* I guess this will never be used since the kernel only
  176. * exports the selector if no divisor is set but hash offset
  177. * and hash mask make only sense in hash filters with divisor
  178. * set */
  179. nl_dump(p, " hash at %u & 0x%x", sel->hoff, sel->hmask);
  180. }
  181. if (sel->flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) {
  182. nl_dump(p, " offset at %u", sel->off);
  183. if (sel->flags & TC_U32_VAROFFSET)
  184. nl_dump(p, " variable (at %u & 0x%x) >> %u",
  185. sel->offoff, ntohs(sel->offmask), sel->offshift);
  186. }
  187. if (sel->flags) {
  188. int flags = sel->flags;
  189. nl_dump(p, " <");
  190. #define PRINT_FLAG(f) if (flags & TC_U32_##f) { \
  191. flags &= ~TC_U32_##f; nl_dump(p, #f "%s", flags ? "," : ""); }
  192. PRINT_FLAG(TERMINAL);
  193. PRINT_FLAG(OFFSET);
  194. PRINT_FLAG(VAROFFSET);
  195. PRINT_FLAG(EAT);
  196. #undef PRINT_FLAG
  197. nl_dump(p, ">");
  198. }
  199. for (i = 0; i < sel->nkeys; i++) {
  200. key = (struct tc_u32_key *) ((char *) sel + sizeof(*sel)) + i;
  201. nl_dump(p, "\n");
  202. nl_dump_line(p, " match key at %s%u ",
  203. key->offmask ? "nexthdr+" : "", key->off);
  204. if (key->offmask)
  205. nl_dump(p, "[0x%u] ", key->offmask);
  206. nl_dump(p, "& 0x%08x == 0x%08x", ntohl(key->mask), ntohl(key->val));
  207. if (p->dp_type == NL_DUMP_STATS &&
  208. (u->cu_mask & U32_ATTR_PCNT)) {
  209. struct tc_u32_pcnt *pcnt = u->cu_pcnt->d_data;
  210. nl_dump(p, " successful %" PRIu64, pcnt->kcnts[i]);
  211. }
  212. }
  213. }
  214. static void u32_dump_details(struct rtnl_tc *tc, void *data,
  215. struct nl_dump_params *p)
  216. {
  217. struct rtnl_u32 *u = data;
  218. struct tc_u32_sel *s;
  219. if (!u)
  220. return;
  221. if (!(u->cu_mask & U32_ATTR_SELECTOR)) {
  222. nl_dump(p, "no-selector\n");
  223. return;
  224. }
  225. s = u->cu_selector->d_data;
  226. nl_dump(p, "nkeys %u ", s->nkeys);
  227. if (u->cu_mask & U32_ATTR_HASH)
  228. nl_dump(p, "ht key 0x%x hash 0x%u",
  229. TC_U32_USERHTID(u->cu_hash), TC_U32_HASH(u->cu_hash));
  230. if (u->cu_mask & U32_ATTR_LINK)
  231. nl_dump(p, "link %u ", u->cu_link);
  232. if (u->cu_mask & U32_ATTR_INDEV)
  233. nl_dump(p, "indev %s ", u->cu_indev);
  234. print_selector(p, s, u);
  235. nl_dump(p, "\n");
  236. }
  237. static void u32_dump_stats(struct rtnl_tc *tc, void *data,
  238. struct nl_dump_params *p)
  239. {
  240. struct rtnl_u32 *u = data;
  241. if (!u)
  242. return;
  243. if (u->cu_mask & U32_ATTR_PCNT) {
  244. struct tc_u32_pcnt *pc = u->cu_pcnt->d_data;
  245. nl_dump(p, "\n");
  246. nl_dump_line(p, " hit %8" PRIu64 " count %8" PRIu64 "\n",
  247. pc->rhit, pc->rcnt);
  248. }
  249. }
  250. static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
  251. {
  252. struct rtnl_u32 *u = data;
  253. if (!u)
  254. return 0;
  255. if (u->cu_mask & U32_ATTR_DIVISOR)
  256. NLA_PUT_U32(msg, TCA_U32_DIVISOR, u->cu_divisor);
  257. if (u->cu_mask & U32_ATTR_HASH)
  258. NLA_PUT_U32(msg, TCA_U32_HASH, u->cu_hash);
  259. if (u->cu_mask & U32_ATTR_CLASSID)
  260. NLA_PUT_U32(msg, TCA_U32_CLASSID, u->cu_classid);
  261. if (u->cu_mask & U32_ATTR_LINK)
  262. NLA_PUT_U32(msg, TCA_U32_LINK, u->cu_link);
  263. if (u->cu_mask & U32_ATTR_SELECTOR)
  264. NLA_PUT_DATA(msg, TCA_U32_SEL, u->cu_selector);
  265. if (u->cu_mask & U32_ATTR_ACTION) {
  266. int err;
  267. err = rtnl_act_fill(msg, TCA_U32_ACT, u->cu_act);
  268. if (err)
  269. return err;
  270. }
  271. if (u->cu_mask & U32_ATTR_POLICE)
  272. NLA_PUT_DATA(msg, TCA_U32_POLICE, u->cu_police);
  273. if (u->cu_mask & U32_ATTR_INDEV)
  274. NLA_PUT_STRING(msg, TCA_U32_INDEV, u->cu_indev);
  275. return 0;
  276. nla_put_failure:
  277. return -NLE_NOMEM;
  278. }
  279. /**
  280. * @name Attribute Modifications
  281. * @{
  282. */
  283. void rtnl_u32_set_handle(struct rtnl_cls *cls, int htid, int hash,
  284. int nodeid)
  285. {
  286. uint32_t handle = (htid << 20) | (hash << 12) | nodeid;
  287. rtnl_tc_set_handle((struct rtnl_tc *) cls, handle );
  288. }
  289. int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid)
  290. {
  291. struct rtnl_u32 *u;
  292. if (!(u = rtnl_tc_data(TC_CAST(cls))))
  293. return -NLE_NOMEM;
  294. u->cu_classid = classid;
  295. u->cu_mask |= U32_ATTR_CLASSID;
  296. return 0;
  297. }
  298. int rtnl_u32_set_divisor(struct rtnl_cls *cls, uint32_t divisor)
  299. {
  300. struct rtnl_u32 *u;
  301. if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
  302. return -NLE_NOMEM;
  303. u->cu_divisor = divisor;
  304. u->cu_mask |= U32_ATTR_DIVISOR;
  305. return 0;
  306. }
  307. int rtnl_u32_set_link(struct rtnl_cls *cls, uint32_t link)
  308. {
  309. struct rtnl_u32 *u;
  310. if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
  311. return -NLE_NOMEM;
  312. u->cu_link = link;
  313. u->cu_mask |= U32_ATTR_LINK;
  314. return 0;
  315. }
  316. int rtnl_u32_set_hashtable(struct rtnl_cls *cls, uint32_t ht)
  317. {
  318. struct rtnl_u32 *u;
  319. if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
  320. return -NLE_NOMEM;
  321. u->cu_hash = ht;
  322. u->cu_mask |= U32_ATTR_HASH;
  323. return 0;
  324. }
  325. int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offset)
  326. {
  327. struct rtnl_u32 *u;
  328. struct tc_u32_sel *sel;
  329. int err;
  330. hashmask = htonl(hashmask);
  331. if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
  332. return -NLE_NOMEM;
  333. sel = u32_selector_alloc(u);
  334. if (!sel)
  335. return -NLE_NOMEM;
  336. err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key));
  337. if(err < 0)
  338. return err;
  339. sel = u32_selector(u);
  340. sel->hmask = hashmask;
  341. sel->hoff = offset;
  342. return 0;
  343. }
  344. int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls)
  345. {
  346. struct rtnl_u32 *u;
  347. struct tc_u32_sel *sel;
  348. int err;
  349. if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
  350. return -NLE_NOMEM;
  351. sel = u32_selector_alloc(u);
  352. if (!sel)
  353. return -NLE_NOMEM;
  354. err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key));
  355. if(err < 0)
  356. return err;
  357. sel = u32_selector(u);
  358. sel->flags |= TC_U32_TERMINAL;
  359. return 0;
  360. }
  361. int rtnl_u32_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
  362. {
  363. struct rtnl_u32 *u;
  364. if (!act)
  365. return 0;
  366. if (!(u = rtnl_tc_data(TC_CAST(cls))))
  367. return -NLE_NOMEM;
  368. u->cu_mask |= U32_ATTR_ACTION;
  369. /* In case user frees it */
  370. rtnl_act_get(act);
  371. return rtnl_act_append(&u->cu_act, act);
  372. }
  373. int rtnl_u32_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
  374. {
  375. struct rtnl_u32 *u;
  376. int ret;
  377. if (!act)
  378. return 0;
  379. if (!(u = rtnl_tc_data(TC_CAST(cls))))
  380. return -NLE_NOMEM;
  381. if (!(u->cu_mask & U32_ATTR_ACTION))
  382. return -NLE_INVAL;
  383. ret = rtnl_act_remove(&u->cu_act, act);
  384. if (ret)
  385. return ret;
  386. if (!u->cu_act)
  387. u->cu_mask &= ~U32_ATTR_ACTION;
  388. rtnl_act_put(act);
  389. return 0;
  390. }
  391. /** @} */
  392. /**
  393. * @name Selector Modifications
  394. * @{
  395. */
  396. int rtnl_u32_set_flags(struct rtnl_cls *cls, int flags)
  397. {
  398. struct tc_u32_sel *sel;
  399. struct rtnl_u32 *u;
  400. if (!(u = rtnl_tc_data(TC_CAST(cls))))
  401. return -NLE_NOMEM;
  402. sel = u32_selector_alloc(u);
  403. if (!sel)
  404. return -NLE_NOMEM;
  405. sel->flags |= flags;
  406. u->cu_mask |= U32_ATTR_SELECTOR;
  407. return 0;
  408. }
  409. /**
  410. * Append new 32-bit key to the selector
  411. *
  412. * @arg cls classifier to be modifier
  413. * @arg val value to be matched (network byte-order)
  414. * @arg mask mask to be applied before matching (network byte-order)
  415. * @arg off offset, in bytes, to start matching
  416. * @arg offmask offset mask
  417. *
  418. * General selectors define the pattern, mask and offset the pattern will be
  419. * matched to the packet contents. Using the general selectors you can match
  420. * virtually any single bit in the IP (or upper layer) header.
  421. *
  422. */
  423. int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask,
  424. int off, int offmask)
  425. {
  426. struct tc_u32_sel *sel;
  427. struct rtnl_u32 *u;
  428. int err;
  429. if (!(u = rtnl_tc_data(TC_CAST(cls))))
  430. return -NLE_NOMEM;
  431. sel = u32_selector_alloc(u);
  432. if (!sel)
  433. return -NLE_NOMEM;
  434. err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key));
  435. if (err < 0)
  436. return err;
  437. /* the selector might have been moved by realloc */
  438. sel = u32_selector(u);
  439. sel->keys[sel->nkeys].mask = mask;
  440. sel->keys[sel->nkeys].val = val & mask;
  441. sel->keys[sel->nkeys].off = off;
  442. sel->keys[sel->nkeys].offmask = offmask;
  443. sel->nkeys++;
  444. u->cu_mask |= U32_ATTR_SELECTOR;
  445. return 0;
  446. }
  447. /**
  448. * Get the 32-bit key from the selector
  449. *
  450. * @arg cls classifier to be retrieve
  451. * @arg index the index of the array of keys, start with 0
  452. * @arg val pointer to store value after masked (network byte-order)
  453. * @arg mask pointer to store the mask (network byte-order)
  454. * @arg off pointer to store the offset
  455. * @arg offmask pointer to store offset mask
  456. *
  457. */
  458. int rtnl_u32_get_key(struct rtnl_cls *cls, uint8_t index,
  459. uint32_t *val, uint32_t *mask, int *off, int *offmask)
  460. {
  461. struct tc_u32_sel *sel;
  462. struct rtnl_u32 *u;
  463. if (!(u = rtnl_tc_data(TC_CAST(cls))))
  464. return -NLE_NOMEM;
  465. if (!(u->cu_mask & U32_ATTR_SELECTOR))
  466. return -NLE_INVAL;
  467. /* the selector might have been moved by realloc */
  468. sel = u32_selector(u);
  469. if (index >= sel->nkeys)
  470. return -NLE_RANGE;
  471. *mask = sel->keys[index].mask;
  472. *val = sel->keys[index].val;
  473. *off = sel->keys[index].off;
  474. *offmask = sel->keys[index].offmask;
  475. return 0;
  476. }
  477. int rtnl_u32_add_key_uint8(struct rtnl_cls *cls, uint8_t val, uint8_t mask,
  478. int off, int offmask)
  479. {
  480. int shift = 24 - 8 * (off & 3);
  481. return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift),
  482. htonl((uint32_t)mask << shift),
  483. off & ~3, offmask);
  484. }
  485. /**
  486. * Append new selector key to match a 16-bit number
  487. *
  488. * @arg cls classifier to be modified
  489. * @arg val value to be matched (host byte-order)
  490. * @arg mask mask to be applied before matching (host byte-order)
  491. * @arg off offset, in bytes, to start matching
  492. * @arg offmask offset mask
  493. */
  494. int rtnl_u32_add_key_uint16(struct rtnl_cls *cls, uint16_t val, uint16_t mask,
  495. int off, int offmask)
  496. {
  497. int shift = ((off & 3) == 0 ? 16 : 0);
  498. if (off % 2)
  499. return -NLE_INVAL;
  500. return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift),
  501. htonl((uint32_t)mask << shift),
  502. off & ~3, offmask);
  503. }
  504. /**
  505. * Append new selector key to match a 32-bit number
  506. *
  507. * @arg cls classifier to be modified
  508. * @arg val value to be matched (host byte-order)
  509. * @arg mask mask to be applied before matching (host byte-order)
  510. * @arg off offset, in bytes, to start matching
  511. * @arg offmask offset mask
  512. */
  513. int rtnl_u32_add_key_uint32(struct rtnl_cls *cls, uint32_t val, uint32_t mask,
  514. int off, int offmask)
  515. {
  516. return rtnl_u32_add_key(cls, htonl(val), htonl(mask),
  517. off & ~3, offmask);
  518. }
  519. int rtnl_u32_add_key_in_addr(struct rtnl_cls *cls, const struct in_addr *addr,
  520. uint8_t bitmask, int off, int offmask)
  521. {
  522. uint32_t mask = 0xFFFFFFFF << (32 - bitmask);
  523. return rtnl_u32_add_key(cls, addr->s_addr, htonl(mask), off, offmask);
  524. }
  525. int rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, const struct in6_addr *addr,
  526. uint8_t bitmask, int off, int offmask)
  527. {
  528. int i, err;
  529. for (i = 1; i <= 4; i++) {
  530. if (32 * i - bitmask <= 0) {
  531. if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1],
  532. 0xFFFFFFFF, off+4*(i-1), offmask)) < 0)
  533. return err;
  534. }
  535. else if (32 * i - bitmask < 32) {
  536. uint32_t mask = 0xFFFFFFFF << (32 * i - bitmask);
  537. if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1],
  538. htonl(mask), off+4*(i-1), offmask)) < 0)
  539. return err;
  540. }
  541. /* otherwise, if (32*i - bitmask >= 32) no key is generated */
  542. }
  543. return 0;
  544. }
  545. /** @} */
  546. static struct rtnl_tc_ops u32_ops = {
  547. .to_kind = "u32",
  548. .to_type = RTNL_TC_TYPE_CLS,
  549. .to_size = sizeof(struct rtnl_u32),
  550. .to_msg_parser = u32_msg_parser,
  551. .to_free_data = u32_free_data,
  552. .to_clone = u32_clone,
  553. .to_msg_fill = u32_msg_fill,
  554. .to_dump = {
  555. [NL_DUMP_LINE] = u32_dump_line,
  556. [NL_DUMP_DETAILS] = u32_dump_details,
  557. [NL_DUMP_STATS] = u32_dump_stats,
  558. },
  559. };
  560. static void __init u32_init(void)
  561. {
  562. rtnl_tc_register(&u32_ops);
  563. }
  564. static void __exit u32_exit(void)
  565. {
  566. rtnl_tc_unregister(&u32_ops);
  567. }
  568. /** @} */