一定要清楚自己在干什么,每行代码在干什么,这样写的代码才能做到心中有数。

之前看到ip_set_hash_ip.chash_ip4_uadt和hash_ip4_kadt函数,就一直很好奇这两个函数是干什么呢?

下面我来带你一步步剖析这两个函数

一、kadt和uadt回调函数的注册

首先看下struct ip_set_type_variant结构体变量

**kadt回调函数的注册在以下三个位置**

1.ip_set_bitmap_gen.h的.kadt = mtype_kadt,

static const struct ip_set_type_variant mtype = {
.kadt = mtype_kadt,
.uadt = mtype_uadt,
.adt = {
[IPSET_ADD] = mtype_add,
[IPSET_DEL] = mtype_del,
[IPSET_TEST] = mtype_test,
},
......
};

2.ip_set_hash_gen.h的.kadt = mtype_kadt,

static const struct ip_set_type_variant mtype_variant = {
.kadt = mtype_kadt,
.uadt = mtype_uadt,
.adt = {
[IPSET_ADD] = mtype_add,
[IPSET_DEL] = mtype_del,
[IPSET_TEST] = mtype_test,
},
......
};

正好对应set模块的三种数据类型bitmap,hash。

其中

.kadt    = mtype_kadt,
.uadt    = mtype_uadt,

搜索mtype_kadt,是一个宏定义,将MTYPE宏定义和_kadt拼接起来
#define CONCAT(a, b)        a##b
#define TOKEN(a, b)        CONCAT(a, b)
#define mtype_kadt        TOKEN(MTYPE, _kadt)
   
MTYPE有不同的定义,对于hash:ip集合,为hash_ip4
#define MTYPE        hash_ip4
那么mtype_kadt宏经过拼装以后得到的是hash_ip4_kadt,即我之前一直疑惑的hash_ip4_kadt函数

ipset的每种类型都需要实现一个xxx_kadt的函数,不信的同学可以打开源代码自己看哦。

二、kadt回调函数的调用位置

调用位置有三处,分别对应于ip_set_test,ip_set_add,ip_set_del函数
1.ip_set_test函数
ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt);

2.ip_set_add函数
ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);

3.ip_set_del函数
ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);

以hash_ip4_kadt为例子进行讲解

hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
              const struct xt_action_param *par,
              enum ipset_adt adt, struct ip_set_adt_opt *opt)
    {
        const struct hash_ip *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ip4_elem e = {};
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
        __be32 ip;
    
        ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
        ip &= ip_set_netmask(h->netmask);
        if (ip == 0)
            return -EINVAL;
    
        e.ip = ip;
        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
    }

在kadt回调函数中会调用adtfn函数

ipset_adtfn adtfn = set->variant->adt[adt];

因此其最终调用还是注册的adt回调函数

在ip_set_hash_gen.h文件中有mtype_add这个函数

那系统是在何时调用ip_set_add呢?

在target回调函数中

这点很好理解了,target回调函数可以说是执行一条指令的最后一步,一切都准备就绪,在target回调函数中调用添加、删除、修改等操作,也是有情可原的。

总结起来流程图如下所示

set->variant->adt继续调用mtype_add函数,此函数位于ip_set_hash_gen.h文件中。

三、uadt回调函数的调用位置

uadt的调用位置有两个

1.call_ad函数

2.IPSET_CBFN(ip_set_utest, struct net *net, struct sock *ctnl,struct sk_buff *skb,const struct nlmsghdr *nlh,
       const struct nlattr * const attr[],struct netlink_ext_ack *extack)

其中IPSET_CBFN宏的功能是创建并实现一个以第一个参数为函数名称的函数,即ip_set_utest函数

搜索ip_set_utest函数,得到结果

其中在IPSET_CMD_TEST项对应的call回调函数用ip_set_utest来赋值,那么call何时调用呢?我们猜测是当IPSET_CMD_TEST请求命令到来时调用call,这些call是内核模块调用的。

暂时没有找到call回调函数是谁来调用的

ipset源代码分析之kadt和uadt回调函数相关推荐

  1. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共 ...

  2. opencv亚像素边缘精度_OpenCV亚像素角点cornerSubPixel()源代码分析

    上一篇博客中讲到了goodFeatureToTrack()这个API函数能够获取图像中的强角点.但是获取的角点坐标是整数,但是通常情况下,角点的真实位置并不一定在整数像素位置,因此为了获取更为精确的角 ...

  3. Scrapy源代码分析-经常使用的爬虫类-CrawlSpider(三)

    CrawlSpider classscrapy.contrib.spiders.CrawlSpider 爬取一般站点经常使用的spider.其定义了一些规则(rule)来提供跟进link的方便的机制. ...

  4. CASSINI源代码分析

    CASSINI源代码分析 2004-11-10 http://blog.csdn.net/shanhe/ 为什么要分析CASSINI? Cassini(卡西尼)是asp.net上的一个开源项目.主要给 ...

  5. KVM虚拟机源代码分析

    1,KVM结构及工作原理 1.1  KVM结构 KVM基本结构有两部分组成.一个是KVM Driver ,已经成为Linux 内核的一个模块.负责虚拟机的创建,虚拟内存的分配,虚拟CPU寄存器的读写以 ...

  6. 基于 linux 平台的 libpcap 源代码分析

    libpcap 是 unix/linux 平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础.Libpcap 可以在绝大多数类 unix 平台下工作,本文分析了 libpcap 在 linu ...

  7. libpcap 源代码分析(二)

    网络监控 绝大多数的现代操作系统都提供了对底层网络数据包捕获的机制,在捕获机制之上可以建立网络监控(Network Monitoring)应用软件.网络监控也常简称为sniffer,其最初的目的在于对 ...

  8. Zepto源代码分析之二~三个API

    因为时间关系:本次仅仅对这三个API($.camelCase.$.contains.$.each)方法进行分析 第一个方法变量转驼峰:$.camelCase('hello-world-welcome' ...

  9. 【Cocos2d-x】源代码分析之 2d/ui/Widget

    从今天開始 咱也模仿 红孩儿这些大牛分析源代码 ,因为水平有限 不正确之处欢迎狂喷.哈哈. #ifndef __UIWIDGET_H__ #define __UIWIDGET_H__#include ...

最新文章

  1. R语言ggplot2可视化将X轴置于ggplot2图表顶部实战
  2. python oracle 运维,mysql oracle python连接
  3. python 局部变量 占内存吗_Python中全局变量和局部变量的理解与区别
  4. django配置在MySQL_怎么在Django中安装与配置mysql
  5. 刷新记录! CVPR2021全新目标检测机制达到SOTA!
  6. OCA读书笔记(8) - 管理用户安全
  7. mysql like n_MySQL LIKE 子句
  8. Python学习week4-set集合
  9. Echarts pie 饼图类型后显示数据
  10. Android中使用FragmentManager获得控件
  11. [BZOJ1415]聪聪和可可
  12. 从分析性数据库ADS中导出数据
  13. 界面设计必备,常用字体规范
  14. 微信服务号使用微信支付
  15. 机器学习sklearn基础(1):多元逻辑回归分类器 (pcolormesh说明及绘图)
  16. CMakeLists.txt范例
  17. python安装pyecharts库_python安装阿里云库pyecharts 安装不上,求大佬指点一下-问答-阿里云开发者社区-阿里云...
  18. SQL中cast和convert的区别
  19. arcgis pro深度学习教程
  20. web编程技术基础---CSS

热门文章

  1. python 创建工具包_创建者工具包–快速创建
  2. python超详细的常用笔记
  3. 关于BGP安全那些事儿
  4. C语言基础应用(三)运算符与表达式
  5. dockerfile启动mysql_dockerfile运行mysql并初始化数据
  6. 在Ubuntu使用Git访问Github
  7. 【OpenGL】光照太阳系
  8. Android 接入华为扫码库,实现堪比微信扫码的效果
  9. python图像处理之图像灰度化
  10. JAVA的第一个程序(HelloWorld)重点解释