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