插入分类器的流表有一个version字段,类型为struct versions,用来标记此流表在哪个version添加到分类器,如果流表被删除后标记在哪个version被删除。

typedef uint64_t ovs_version_t;#define OVS_VERSION_MIN 0                  /* Default version number to use. */
//可用版本的最大值,为ovs_version_t-1
#define OVS_VERSION_MAX (TYPE_MAXIMUM(ovs_version_t) - 1)
//添加流表时,remove_version被设置此值,表示此流表被添加,还没被删除
#define OVS_VERSION_NOT_REMOVED TYPE_MAXIMUM(ovs_version_t)/** OVS_VERSION_NOT_REMOVED has a special meaning for 'remove_version',* meaning that the rule has been added but not yet removed.*/
struct versions {ovs_version_t add_version;              /* Version object was added in. */ATOMIC(ovs_version_t) remove_version;   /* Version object is removed in. */
};//插入分类器的结构,代表一个流表
struct cls_match {.../* Rule versioning. */struct versions versions;...
};

结构体struct ofproto代表一个ovs网桥,其中字段tables_version用来控制哪些流表可被查询到,每次流表更新都会导致其值增加1。

struct ofproto {...ovs_version_t tables_version;  /* Controls which rules are visible to table lookups. */...
}

struct cls_match的versions字段是在添加流表时被赋值,其中
add_version为当前ofproto->tables_version的值,remove_version为OVS_VERSION_NOT_REMOVED。这样的话,查询流表时,只有ofproto->tables_version在add_version和remove_version范围内的流表才能被匹配。当删除此流表时,add_version值不变,但是remove_version被更新成当前ofproto->tables_version的值,由于ofproto->tables_version的值是不断增长的,所以流表被删除后,ofproto->tables_version的值肯定是大于remove_version的,所以查询流表时,相当于此流表是不可见的。

version的更新

handle_flow_mod__(struct ofproto *ofproto, const struct ofputil_flow_mod *fm, const struct openflow_mod_requester *req)//每次添加,更新或者删除流表 ofproto->tables_version都要加一ofm.version = ofproto->tables_version + 1;//添加流表时,设置 add_version 为 ofm.version,remove_version 为 OVS_VERSION_NOT_REMOVEDofproto_flow_mod_start(ofproto, &ofm);add_flow_start(ofproto, ofm);replace_rule_start(ofproto, ofm, old_rule, new_rule);//将流表插入分类器classifier_insert(&table->cls, &new_rule->cr, ofm->version, ofm->conjs, ofm->n_conjs);classifier_replace(cls, rule, version, conj, n_conj);//分配 cls_match,struct cls_match *new;new = cls_match_alloc(rule, version, conjs, n_conjs);struct cls_match *cls_match = xmalloc(sizeof *cls_match + MINIFLOW_VALUES_SIZE(count));//versions的 add_version 和 remove_version 都被初始化为 version/* Make rule initially invisible. */cls_match->versions = VERSIONS_INITIALIZER(version, version);...//将流表插入分类器后,就可以将 remove_version 设置为 OVS_VERSION_NOT_REMOVED,//可被 classifier_lookup 查询到/* Make 'new' visible to lookups in the appropriate version. */cls_match_set_remove_version(new, OVS_VERSION_NOT_REMOVED);versions_set_remove_version(&rule->versions, version);atomic_store_relaxed(&versions->remove_version, version);//删除流表时,设置 remove_version 为 ofm.version,表示从ofm.version后的版本都不能查询到此流表delete_flow_start_strict(ofproto, ofm);delete_flows_start__(ofproto, ofm->version, rules);struct rule *rule;RULE_COLLECTION_FOR_EACH (rule, rules) {struct oftable *table = &ofproto->tables[rule->table_id];table->n_flows--;//设置 remove_version 为 ofm.version,设置完后后面查找流表时就查不到它了cls_rule_make_invisible_in_version(&rule->cr, version);struct cls_match *cls_match = get_cls_match_protected(rule);cls_match_set_remove_version(cls_match, remove_version);versions_set_remove_version(&rule->versions, version);atomic_store_relaxed(&versions->remove_version, version);}//ofproto->tables_version加1,并更新到 struct ofproto_dpif->tables_versionofproto_bump_tables_version(ofproto);++ofproto->tables_version;ofproto->ofproto_class->set_tables_version(ofproto,ofproto->tables_version);struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);/* Use memory_order_release to signify that any prior memory accesses can* not be reordered to happen after this atomic store.  This makes sure the* new version is properly set up when the readers can read this 'version'* value. */atomic_store_explicit(&ofproto->tables_version, version, memory_order_release);/* 'need_revalidate' can be reordered to happen before the atomic_store* above, but it does not matter as this variable is not accessed by other* threads. */ofproto->backer->need_revalidate = REV_FLOW_TABLE;

使用version查询流表
只有struct ofproto_dpif->tables_version

//查询流表时,首先获取 struct ofproto_dpif->tables_version,只有此值在流表的 add_version 和 remove_version
//之间的流表才能被匹配
ovs_version_t
ofproto_dpif_get_tables_version(struct ofproto_dpif *ofproto)
{ovs_version_t version;/* Use memory_order_acquire to signify that any following memory accesses* can not be reordered to happen before this atomic read.  This makes sure* all following reads relate to this or a newer version, but never to an* older version. */atomic_read_explicit(&ofproto->tables_version, &version, memory_order_acquire);return version;
}//查询openflow流表
upcall_xlate//ofproto_dpif_get_tables_version获取 ofproto->tables_versionxlate_in_init(&xin, upcall->ofproto,ofproto_dpif_get_tables_version(upcall->ofproto),upcall->flow, upcall->in_port, NULL,stats.tcp_flags, upcall->packet, wc, odp_actions);xin->ofproto = ofproto;xin->tables_version = version;...xlate_actions(&xin, &upcall->xout);struct xlate_ctx ctx = {.xin = xin,...};//开始遍历ofproto的流表rule_dpif_lookup_from_table(ctx.xbridge->ofproto, ctx.xin->tables_version, flow, ctx.wc,ctx.xin->resubmit_stats, &ctx.table_id,flow->in_port.ofp_port, true, true, ctx.xin->xcache);struct rule_dpif *rule;for (next_id = *table_id;next_id < ofproto->up.n_tables;next_id++, next_id += (next_id == TBL_INTERNAL)){*table_id = next_id;rule = rule_dpif_lookup_in_table(ofproto, version, next_id, flow, wc);classifier_lookup(cls, version, flow, wc)classifier_lookup__(cls, version, flow, wc, true);find_match_wc(subtable, version, flow, trie_ctx, cls->n_tries, wc);find_match(subtable, version, flow, hash);//只有可见的流表才能被匹配,//即大于add_version,并且小于remove_version的流表才能被匹配cls_match_visible_in_version(rule, version)versions_visible_in_version(&rule->versions, version);ovs_version_t remove_version;/* C11 does not want to access an atomic via a const object pointer. */atomic_read_relaxed(&CONST_CAST(struct versions *,versions)->remove_version,&remove_version);return versions->add_version <= version && version < remove_version;}

这里还有个疑问,前面说到不管增加还是删除流表ofproto->tables_version是一直增长的,虽然它的类型是uint64_t,是个很大的值,但是如果进程不重启,随着时间拉长,总会溢出反转成0的,这样的话,前面添加的流表就查不到了。

可以做个试验,创建一个网桥,两个namespace,两对veth口,分别连接到网桥和namespace,每个namespace中的veth口配置同网段ip,再添加如下两条流表,此时是可以互相ping通的。

ovs-ofctl add-flow br10 "priority=80, in_port=2, action=1"
ovs-ofctl add-flow br10 "priority=80, in_port=1, action=2"

在添加上面流表时,通过gdb ovs-vswitchd进程,在函数handle_flow_mod__观察到ofproto->tables_version为18和19,
此时两条流表的version分别为

flow1: add_version = 18, remove_version = OVS_VERSION_NOT_REMOVED
flow2: add_version = 19, remove_version = OVS_VERSION_NOT_REMOVED

ofproto->tables_version的值为19,所以在查询流表时,这两条流表是可见的。

但是如果在gdb中强制将ofproto->tables_version改为0,模拟ofproto->tables_version溢出反转的情况,发现两个namespace互相ping不同的。因为ofproto->tables_version不在流表的add_version 和remove_version 范围。查询流表时,查不到这两条流表就会drop报文。

这种情况不太清楚ovs是怎么解决的,莫非就是期望ofproto->tables_version不会溢出反转?知道的同学留个言告知下,多谢

也可参考:ovs 流表version - 简书 (jianshu.com)

ovs 流表version相关推荐

  1. Mellanox CX-5网卡支持OVS流表加速功能的调研

    女主宣言 本文主要对Mellanox CX-5网卡支持OVS流表加速功能进行了调研,简单介绍了配套软件的版本要求,并描述了整体测试的步骤,另外对其支持VF热迁移也进行了初步的调研,希望对有相同需求的同 ...

  2. OVS 流表轨迹入门及典型场景举例【ovs-appctl ofproto/trace】

    OVS 流表轨迹入门及典型场景举例 一. 流表轨迹入门 二. 典型场景举例 三. 小技巧 一. 流表轨迹入门 在数据中心网络中,SDN控制器通过向OVS交换机下发OpenFlow流表,指导报文转发.在 ...

  3. OVS流表精确匹配TCP/IP报头五元组

    ---------------- 版权:本文转自cnblogs 刘超的通俗云计算 原文链接: https://www.cnblogs.com/popsuper1982/p/5870181.html h ...

  4. OVN 流表基础 -- 基于 kubeOVN (一)

    文章目录 Kubectl ko 工具分析 Nbctl Sbctl Trace Ovn 流表 Match Action Register Table 介绍 Logical Switch Datapath ...

  5. Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(8)

    问题导读: 1.怎样使用arp_responder ? 2.怎样搭建l2pop环境? 3. ARP Responder arp_responder 的原理不复杂.Neutorn DB 中保存了所有的端 ...

  6. ovs 删除openflow流表

    有如下三种方法可以删除openflow流表: a. controller/ovs-ofctl主动发命令(OFPFC_DELETE or OFPFC_DELETE_STRICT)删除流表.OFPFC_D ...

  7. ovs 添加流表流程

    可以通过controller或者ovs-ofctl命令给网桥添加流表,这篇文章以ovs-ofctl添加流表为例,看一下如何解析匹配域和action,如何发送openflow消息给网桥及ovs-vswi ...

  8. OVS中arp响应的流表的实现

    总结: 1.br-int 流表总体是按照Normal 的方式,即常规的交换机的转发方式进行转发.而br-tun 交换机则主要按照流表的方式进行转发. 2.一般情况下,VM发出的ARP请求,会在该VM的 ...

  9. Mininet+OVS:如何更改SDN交换机的流表条目上限

    前言 流表是SDN交换机转发的重要环节.当一个不匹配的流量进入交换机时,交换机通过packet-in上报控制器,控制器以flow-mod应答,并在交换机中安装对应规则. OVS中提供了对于流表的支持, ...

最新文章

  1. php判断是否已关注,php判断用户是否关注微信订阅号或公众号
  2. learnpython有中文版吗_简介 | Learn Python the Hard Way 中文版
  3. ASP.NET 2.0(C#) - Themes(主题)
  4. ionic2 mac android,Ionic制作Hybrid App系列二:Mac环境下Ionic release版本APK的签名与发布...
  5. 6-14 数据库高级
  6. [转]不知道能否解决先转下来再说不显示删除回复显示所有回复显示星级回复显示得分回复 没有找到MSVR90D.dll因此这个应用程序未能启动...
  7. Django + Uwsgi + Nginx 实现生产环境部署1
  8. springboot默认数据源如何设置连接数_Spring Boot学习:如何使用Druid数据源
  9. C语言谭浩强博客,折半查找法--C语言谭浩强版练习6.9
  10. 线性反馈移位寄存器(LFSR,Linear Feedback Shift Register)
  11. Seven languages in seven weeks (notes on Scala)
  12. 【图像处理】多光谱 波长波段划分 主要波段特性 植被遥感原理 典型植被指数
  13. python实现10进制转换2进制(两种方法)
  14. 利用树莓派4搭建私有云盘
  15. 如何 重构网络 SDN架构实现
  16. JVM垃圾回收器G1详解
  17. 2023年五一数学建模竞赛ABC题思路资料汇总贴
  18. join()方法的使用
  19. 5W1H1V分析法帮你快速了解产品
  20. 【人工智能】大模型的发展历史

热门文章

  1. Java好资源网址推荐
  2. 手把手教你入门R语言--数据分析篇(1)——数据导入与基础绘图
  3. JavaScript - Objects
  4. 【20190423】【笔经、面经集】2019年暑期实习找工作经历,分享给大家,也给自己长个记性~(持续更新)
  5. 什么是数字体验平台(DXP)?
  6. linux redhat 版本查看,查看RedHat linux版本的三种方法
  7. windows常用DOS命令
  8. 使用feign发送http请求解析报错
  9. Caused by: java.nio.file.FileSystemException: ..... : 打开的文件过多
  10. bittorrent_Bittorrent的漩涡:使用Torrent托管网站