inet_hook_ops实例
struct inet_hook_ops {//处理函数inet_hook_fn hook;//Inet hook点,类似linux内核netfilterunsigned int hooknum;//协议族,AF_INET、AF_INET6int af;//私有数据void *priv;//优先级,同一hook_num处实例,通过priority从小到大链接在双向链表中,priority值越小,对应优先级越高int priority;//同一hooknum存在多个inet_hook_ops实例,通过list构成双向链表struct list_head list; };hooks定义
enum {INET_HOOK_PRE_ROUTING,INET_HOOK_LOCAL_IN,INET_HOOK_FORWARD,INET_HOOK_LOCAL_OUT,INET_HOOK_POST_ROUTING,INET_HOOK_NUMHOOKS, };hook处理函数返回值
enum {INET_DROP = 0,INET_ACCEPT,INET_STOLEN,INET_REPEAT,INET_STOP,INET_VERDICT_NUM, };全局的inet_hook_ops实例数组
//AF_INET协议族相关inet_hook_ops hash组织结构,inet_hooks[hook_num]指向对应hook_num处链表头 static struct list_head inet_hooks[INET_HOOK_NUMHOOKS]; static rte_rwlock_t inet_hook_lock; //AF-INET6协议族相关inet_hook_ops hash组织结构,inet6_hooks[hook_num]指向对应hook_num处链表头 static struct list_head inet6_hooks[INET_HOOK_NUMHOOKS]; static rte_rwlock_t inet6_hook_lock; //获取对应协议族,对应hook_num处inet_hook_ops链表头 static inline struct list_head *af_inet_hooks(int af, size_t num) {assert((af == AF_INET || af == AF_INET6) && num < INET_HOOK_NUMHOOKS);if (af == AF_INET)return &inet_hooks[num];elsereturn &inet6_hooks[num]; } //获取对应锁 static inline rte_rwlock_t *af_inet_hook_lock(int af) {assert(af == AF_INET || af == AF_INET6);if (af == AF_INET)return &inet_hook_lock;elsereturn &inet6_hook_lock; }inet_hook_ops注册
int inet_register_hooks(struct inet_hook_ops *reg, size_t n) {int af;size_t i, err;struct list_head *hook_list;assert(reg);for (i = 0; i < n; i++) {af = reg[i].af;//校验hooknum正确性if (reg[i].hooknum >= INET_HOOK_NUMHOOKS || !reg[i].hook) {err = EDPVS_INVAL;goto rollback;}//获取对应协议族和hook_num的链表头hook_list = af_inet_hooks(af, reg[i].hooknum);rte_rwlock_write_lock(af_inet_hook_lock(af));//通过priority插入到链表正确位置err = __inet_register_hooks(hook_list, ®[i]);rte_rwlock_write_unlock(af_inet_hook_lock(af));if (err != EDPVS_OK)goto rollback;}return EDPVS_OK;rollback:inet_unregister_hooks(reg, n);return err; }static int __inet_register_hooks(struct list_head *head,struct inet_hook_ops *reg) {struct inet_hook_ops *elem;/* check if exist */list_for_each_entry(elem, head, list) {if (elem == reg) {RTE_LOG(ERR, INET, "%s: hook already exist\\n", __func__);return EDPVS_EXIST; /* error ? */}}list_for_each_entry(elem, head, list) {if (reg->priority < elem->priority)break;}list_add(®->list, elem->list.prev);return EDPVS_OK; }inet_hook_ops unregister
int inet_unregister_hooks(struct inet_hook_ops *reg, size_t n) {int af;size_t i;struct inet_hook_ops *elem, *next;struct list_head *hook_list;assert(reg);for (i = 0; i < n; i++) {af = reg[i].af;if (reg[i].hooknum >= INET_HOOK_NUMHOOKS) {RTE_LOG(WARNING, INET, "%s: bad hook number\\n", __func__);continue; /* return error ? */}hook_list = af_inet_hooks(af, reg[i].hooknum);#ifdef CONFIG_DPVS_IPV4_INET_HOOKrte_rwlock_write_lock(&inet_hook_lock); #endiflist_for_each_entry_safe(elem, next, hook_list, list) {if (elem == ®[i]) {list_del(&elem->list);break;}} #ifdef CONFIG_DPVS_IPV4_INET_HOOKrte_rwlock_write_unlock(&inet_hook_lock); #endifif (&elem->list == hook_list)RTE_LOG(WARNING, INET, "%s: hook not found\\n", __func__);}return EDPVS_OK; }INET_HOOK处理流程
int INET_HOOK(int af, unsigned int hook, struct rte_mbuf *mbuf,struct netif_port *in, struct netif_port *out,int (*okfn)(struct rte_mbuf *mbuf)) {struct list_head *hook_list;struct inet_hook_ops *ops;struct inet_hook_state state;//默认为ACCPT动作int verdict = INET_ACCEPT;state.hook = hook;//获取对应hook处的inet_hook_ops链表头hook_list = af_inet_hooks(af, hook);ops = list_entry(hook_list, struct inet_hook_ops, list);if (!list_empty(hook_list)) {verdict = INET_ACCEPT;//遍历回调函数数组,并执行.根据返回值来判断是否继续执行等list_for_each_entry_continue(ops, hook_list, list) { repeat:verdict = ops->hook(ops->priv, mbuf, &state);//如果inet_hook_ops返回结构不是INET_ACCEPT时,判断是否是INET_REPEAT动作,如果是则要再次进入该inet_hook_ops,//此处应该注意不能陷入无限循环中;否则终止此处hook函数执行if (verdict != INET_ACCEPT) {if (verdict == INET_REPEAT)goto repeat;break;}}}//如果hook判定动作为ACCEPT或者STOP,则执行接下来的okfn函数,例如ipv4处理中的ipv4_rcv_finif (verdict == INET_ACCEPT || verdict == INET_STOP) {return okfn(mbuf);} else if (verdict == INET_DROP) {//处理动作为DROP,丢弃数据包rte_pktmbuf_free(mbuf);return EDPVS_DROP;} else { /* INET_STOLEN *///如果返回INET_STOLEN,则数据包处理到此为止,不会再往上投递处理,okfn也不会调用return EDPVS_OK;} }inet_hook_init
- 对全局的hash数组链表头和用于同步的锁进行初始化
static int inet_hook_init(void) {int i;rte_rwlock_init(&inet_hook_lock);rte_rwlock_write_lock(&inet_hook_lock);for (i = 0; i < NELEMS(inet_hooks); i++)INIT_LIST_HEAD(&inet_hooks[i]);rte_rwlock_write_unlock(&inet_hook_lock);rte_rwlock_init(&inet6_hook_lock);rte_rwlock_write_lock(&inet6_hook_lock);for (i = 0; i < NELEMS(inet6_hooks); i++)INIT_LIST_HEAD(&inet6_hooks[i]);rte_rwlock_write_unlock(&inet6_hook_lock);return EDPVS_OK; }
详细解决方案
INET_HOOK
热度:67 发布时间:2024-02-12 07:56:00.0
相关解决方案