当前位置: 代码迷 >> 综合 >> INET_HOOK
  详细解决方案

INET_HOOK

热度:67   发布时间:2024-02-12 07:56:00.0
  • 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, &reg[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(&reg->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 == &reg[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;
    }
    
  相关解决方案