act_generic.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * include/net/act_generic.h
  3. *
  4. */
  5. #ifndef _NET_ACT_GENERIC_H
  6. #define _NET_ACT_GENERIC_H
  7. static inline int tcf_defact_release(struct tcf_defact *p, int bind)
  8. {
  9. int ret = 0;
  10. if (p) {
  11. if (bind) {
  12. p->bindcnt--;
  13. }
  14. p->refcnt--;
  15. if (p->bindcnt <= 0 && p->refcnt <= 0) {
  16. kfree(p->defdata);
  17. tcf_hash_destroy(p);
  18. ret = 1;
  19. }
  20. }
  21. return ret;
  22. }
  23. static inline int
  24. alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
  25. {
  26. p->defdata = kmalloc(datalen, GFP_KERNEL);
  27. if (p->defdata == NULL)
  28. return -ENOMEM;
  29. p->datalen = datalen;
  30. memcpy(p->defdata, defdata, datalen);
  31. return 0;
  32. }
  33. static inline int
  34. realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
  35. {
  36. /* safer to be just brute force for now */
  37. kfree(p->defdata);
  38. return alloc_defdata(p, datalen, defdata);
  39. }
  40. static inline int
  41. tcf_defact_init(struct rtattr *rta, struct rtattr *est,
  42. struct tc_action *a, int ovr, int bind)
  43. {
  44. struct rtattr *tb[TCA_DEF_MAX];
  45. struct tc_defact *parm;
  46. struct tcf_defact *p;
  47. void *defdata;
  48. u32 datalen = 0;
  49. int ret = 0;
  50. if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
  51. return -EINVAL;
  52. if (tb[TCA_DEF_PARMS - 1] == NULL ||
  53. RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))
  54. return -EINVAL;
  55. parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
  56. defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
  57. if (defdata == NULL)
  58. return -EINVAL;
  59. datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
  60. if (datalen <= 0)
  61. return -EINVAL;
  62. p = tcf_hash_check(parm->index, a, ovr, bind);
  63. if (p == NULL) {
  64. p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
  65. if (p == NULL)
  66. return -ENOMEM;
  67. ret = alloc_defdata(p, datalen, defdata);
  68. if (ret < 0) {
  69. kfree(p);
  70. return ret;
  71. }
  72. ret = ACT_P_CREATED;
  73. } else {
  74. if (!ovr) {
  75. tcf_defact_release(p, bind);
  76. return -EEXIST;
  77. }
  78. realloc_defdata(p, datalen, defdata);
  79. }
  80. spin_lock_bh(&p->lock);
  81. p->action = parm->action;
  82. spin_unlock_bh(&p->lock);
  83. if (ret == ACT_P_CREATED)
  84. tcf_hash_insert(p);
  85. return ret;
  86. }
  87. static inline int tcf_defact_cleanup(struct tc_action *a, int bind)
  88. {
  89. struct tcf_defact *p = PRIV(a, defact);
  90. if (p != NULL)
  91. return tcf_defact_release(p, bind);
  92. return 0;
  93. }
  94. static inline int
  95. tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
  96. {
  97. unsigned char *b = skb->tail;
  98. struct tc_defact opt;
  99. struct tcf_defact *p = PRIV(a, defact);
  100. struct tcf_t t;
  101. opt.index = p->index;
  102. opt.refcnt = p->refcnt - ref;
  103. opt.bindcnt = p->bindcnt - bind;
  104. opt.action = p->action;
  105. RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
  106. RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata);
  107. t.install = jiffies_to_clock_t(jiffies - p->tm.install);
  108. t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
  109. t.expires = jiffies_to_clock_t(p->tm.expires);
  110. RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
  111. return skb->len;
  112. rtattr_failure:
  113. skb_trim(skb, b - skb->data);
  114. return -1;
  115. }
  116. #define tca_use_default_ops \
  117. .dump = tcf_defact_dump, \
  118. .cleanup = tcf_defact_cleanup, \
  119. .init = tcf_defact_init, \
  120. .walk = tcf_generic_walker, \
  121. #define tca_use_default_defines(name) \
  122. static u32 idx_gen; \
  123. static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \
  124. static DEFINE_RWLOCK(##name_lock);
  125. #endif /* _NET_ACT_GENERIC_H */