mirred.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * lib/route/cls/mirred.c mirred action
  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) 2013 Cong Wang <xiyou.wangcong@gmail.com>
  10. */
  11. /**
  12. * @ingroup act
  13. * @defgroup act_mirred Mirror and Redirect
  14. *
  15. * @{
  16. */
  17. #include <netlink-private/netlink.h>
  18. #include <netlink-private/tc.h>
  19. #include <netlink/netlink.h>
  20. #include <netlink/attr.h>
  21. #include <netlink/utils.h>
  22. #include <netlink-private/route/tc-api.h>
  23. #include <netlink/route/act/mirred.h>
  24. static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
  25. [TCA_MIRRED_PARMS] = { .minlen = sizeof(struct tc_mirred) },
  26. };
  27. static int mirred_msg_parser(struct rtnl_tc *tc, void *data)
  28. {
  29. struct rtnl_mirred *u = data;
  30. struct nlattr *tb[TCA_MIRRED_MAX + 1];
  31. int err;
  32. err = tca_parse(tb, TCA_MIRRED_MAX, tc, mirred_policy);
  33. if (err < 0)
  34. return err;
  35. if (!tb[TCA_MIRRED_PARMS])
  36. return -NLE_MISSING_ATTR;
  37. nla_memcpy(&u->m_parm, tb[TCA_MIRRED_PARMS], sizeof(u->m_parm));
  38. return 0;
  39. }
  40. static void mirred_free_data(struct rtnl_tc *tc, void *data)
  41. {
  42. }
  43. static int mirred_clone(void *_dst, void *_src)
  44. {
  45. struct rtnl_mirred *dst = _dst, *src = _src;
  46. memcpy(&dst->m_parm, &src->m_parm, sizeof(src->m_parm));
  47. return 0;
  48. }
  49. static void mirred_dump_line(struct rtnl_tc *tc, void *data,
  50. struct nl_dump_params *p)
  51. {
  52. struct rtnl_mirred *u = data;
  53. if (!u)
  54. return;
  55. nl_dump(p, " index %u", u->m_parm.ifindex);
  56. if (u->m_parm.eaction == TCA_EGRESS_MIRROR)
  57. nl_dump(p, " egress mirror");
  58. else if (u->m_parm.eaction == TCA_EGRESS_REDIR)
  59. nl_dump(p, " egress redirect");
  60. switch(u->m_parm.action) {
  61. case TC_ACT_UNSPEC:
  62. nl_dump(p, " unspecified");
  63. break;
  64. case TC_ACT_PIPE:
  65. nl_dump(p, " pipe");
  66. break;
  67. case TC_ACT_STOLEN:
  68. nl_dump(p, " stolen");
  69. break;
  70. case TC_ACT_SHOT:
  71. nl_dump(p, " shot");
  72. break;
  73. case TC_ACT_QUEUED:
  74. nl_dump(p, " queued");
  75. break;
  76. case TC_ACT_REPEAT:
  77. nl_dump(p, " repeat");
  78. break;
  79. }
  80. }
  81. static void mirred_dump_details(struct rtnl_tc *tc, void *data,
  82. struct nl_dump_params *p)
  83. {
  84. }
  85. static void mirred_dump_stats(struct rtnl_tc *tc, void *data,
  86. struct nl_dump_params *p)
  87. {
  88. struct rtnl_mirred *u = data;
  89. if (!u)
  90. return;
  91. /* TODO */
  92. }
  93. static int mirred_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
  94. {
  95. struct rtnl_mirred *u = data;
  96. if (!u)
  97. return 0;
  98. NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(u->m_parm), &u->m_parm);
  99. return 0;
  100. nla_put_failure:
  101. return -NLE_NOMEM;
  102. }
  103. /**
  104. * @name Attribute Modifications
  105. * @{
  106. */
  107. int rtnl_mirred_set_action(struct rtnl_act *act, int action)
  108. {
  109. struct rtnl_mirred *u;
  110. if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
  111. return -NLE_NOMEM;
  112. if (action > TCA_INGRESS_MIRROR || action < TCA_EGRESS_REDIR)
  113. return -NLE_INVAL;
  114. switch (action) {
  115. case TCA_EGRESS_MIRROR:
  116. case TCA_EGRESS_REDIR:
  117. u->m_parm.eaction = action;
  118. break;
  119. case TCA_INGRESS_REDIR:
  120. case TCA_INGRESS_MIRROR:
  121. default:
  122. return NLE_OPNOTSUPP;
  123. }
  124. return 0;
  125. }
  126. int rtnl_mirred_get_action(struct rtnl_act *act)
  127. {
  128. struct rtnl_mirred *u;
  129. if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
  130. return -NLE_NOMEM;
  131. return u->m_parm.eaction;
  132. }
  133. int rtnl_mirred_set_ifindex(struct rtnl_act *act, uint32_t ifindex)
  134. {
  135. struct rtnl_mirred *u;
  136. if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
  137. return -NLE_NOMEM;
  138. u->m_parm.ifindex = ifindex;
  139. return 0;
  140. }
  141. uint32_t rtnl_mirred_get_ifindex(struct rtnl_act *act)
  142. {
  143. struct rtnl_mirred *u;
  144. if ((u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
  145. return u->m_parm.ifindex;
  146. return 0;
  147. }
  148. int rtnl_mirred_set_policy(struct rtnl_act *act, int policy)
  149. {
  150. struct rtnl_mirred *u;
  151. if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
  152. return -NLE_NOMEM;
  153. if (policy > TC_ACT_REPEAT || policy < TC_ACT_OK)
  154. return -NLE_INVAL;
  155. switch (u->m_parm.eaction) {
  156. case TCA_EGRESS_MIRROR:
  157. case TCA_EGRESS_REDIR:
  158. u->m_parm.action = policy;
  159. break;
  160. case TCA_INGRESS_REDIR:
  161. case TCA_INGRESS_MIRROR:
  162. default:
  163. return NLE_OPNOTSUPP;
  164. }
  165. return 0;
  166. }
  167. int rtnl_mirred_get_policy(struct rtnl_act *act)
  168. {
  169. struct rtnl_mirred *u;
  170. if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
  171. return -NLE_NOMEM;
  172. return u->m_parm.action;
  173. }
  174. /** @} */
  175. static struct rtnl_tc_ops mirred_ops = {
  176. .to_kind = "mirred",
  177. .to_type = RTNL_TC_TYPE_ACT,
  178. .to_size = sizeof(struct rtnl_mirred),
  179. .to_msg_parser = mirred_msg_parser,
  180. .to_free_data = mirred_free_data,
  181. .to_clone = mirred_clone,
  182. .to_msg_fill = mirred_msg_fill,
  183. .to_dump = {
  184. [NL_DUMP_LINE] = mirred_dump_line,
  185. [NL_DUMP_DETAILS] = mirred_dump_details,
  186. [NL_DUMP_STATS] = mirred_dump_stats,
  187. },
  188. };
  189. static void __init mirred_init(void)
  190. {
  191. rtnl_tc_register(&mirred_ops);
  192. }
  193. static void __exit mirred_exit(void)
  194. {
  195. rtnl_tc_unregister(&mirred_ops);
  196. }
  197. /** @} */