不同于NAT/DR/Tunnel转发模式,bypass模式不能够通过ipvsadm命令行显示的指定,而是在调度失败之后,可能进入的一种转发模式,由内核自动决定。

对于UDP、TCP和SCTP协议,在调度过程中,如果连接创建失败,例如由于未找到合适的目的调度服务器、内存不足等原因,ignored变量小于等于零的情况发生。其中ignored小于零,表明内存分配失败导致的连接创建失败,此时verdict设置为NF_DROP,结束执行。

如果ignored等于零,表明未找到合适的目的服务器,此种情况下由函数ip_vs_leave进行进一步处理。

static int udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,struct ip_vs_proto_data *pd, int *verdict, struct ip_vs_conn **cpp, struct ip_vs_iphdr *iph)
{/* Let the virtual server select a real server for the incoming connection, and create a connection entry.*/*cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);if (!*cpp && ignored <= 0) {if (!ignored)*verdict = ip_vs_leave(svc, skb, pd, iph);else*verdict = NF_DROP;return 0;

以下TCP协议的调度处理函数tcp_conn_schedule,涉及连接创建失败的处理与以上UDP协议的处理相同。

 34 static int tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,36           struct ip_vs_proto_data *pd, int *verdict, struct ip_vs_conn **cpp, struct ip_vs_iphdr *iph)39 {90         *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);91         if (!*cpp && ignored <= 0) {92             if (!ignored)93                 *verdict = ip_vs_leave(svc, skb, pd, iph);94             else95                 *verdict = NF_DROP;96             return 0;

以下SCTP协议的调度处理函数sctp_conn_schedule,涉及连接创建失败的处理与以上UDP协议的处理相同。

static int sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,struct ip_vs_proto_data *pd, int *verdict, struct ip_vs_conn **cpp, struct ip_vs_iphdr *iph)
{*cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);if (!*cpp && ignored <= 0) {if (!ignored)*verdict = ip_vs_leave(svc, skb, pd, iph);else*verdict = NF_DROP;return 0;

未调度报文处理

如上所述,ip_vs_leave函数负责处理未成功调度的报文。首先通过函数frag_safe_skb_hp安全的获取到目的端口号,四层协议(如UDP、TCP等)的端口号信息的偏移位于IP头部之后,即offset为iph->len,此函数确保无论offset偏移是位于skb缓存的线性区,或者是共享缓存区都可安全的获取到端口号所在缓存的起始指针pptr。

/**  Pass or drop the packet.*  Called by ip_vs_in, when the virtual service is available but*  no destination is available for a new connection.*/
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph)
{__be16 _ports[2], *pptr, dport;struct netns_ipvs *ipvs = svc->ipvs;struct net *net = ipvs->net;pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);if (!pptr)return NF_DROP;dport = likely(!ip_vs_iph_inverse(iph)) ? pptr[1] : pptr[0];

如果IPVS虚拟服务是使用防火墙标记fwmark设定的,并且报文的目的地址为单播地址,而且此报文不是ICMP报文,其也不是回复方向的报文,即为原始请求报文,符合以上所有的条件,并且内核开启了cache_bypass功能,尝试将报文按照其IP头部的目的地址进行转发。

可通过PROC文件/proc/sys/net/ipv4/vs/cache_bypass修改sysctl_cache_bypass的值,默认情况下为零,即丢弃未找到目的服务器的报文。

    /* if it is fwmark-based service, the cache_bypass sysctl is up and the destination is a non-local unicast, then createa cache_bypass connection entry */if (sysctl_cache_bypass(ipvs) && svc->fwmark &&!(iph->hdr_flags & (IP_VS_HDR_INVERSE | IP_VS_HDR_ICMP)) &&ip_vs_addr_is_unicast(net, svc->af, &iph->daddr)) {int ret;struct ip_vs_conn *cp;unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET && iph->protocol == IPPROTO_UDP) ? IP_VS_CONN_F_ONE_PACKET : 0;union nf_inet_addr daddr =  { .all = { 0, 0, 0, 0 } };

如果cache_bypass开启,以下创建一个新的连接结构,其中指定连接标志IP_VS_CONN_F_BYPASS标志,表示此链接为一个bypass类型连接,并为此连接绑定IP_VS_CONN_F_BYPASS类型的传输函数ip_vs_bypass_xmit。

        /* create a new connection entry */{struct ip_vs_conn_param p;ip_vs_conn_fill_param(svc->ipvs, svc->af, iph->protocol, &iph->saddr, pptr[0], &iph->daddr, pptr[1], &p);cp = ip_vs_conn_new(&p, svc->af, &daddr, 0, IP_VS_CONN_F_BYPASS | flags, NULL, skb->mark);if (!cp)return NF_DROP;}

以下调用连接绑定的packet_xmit发送函数,即ip_vs_bypass_xmit函数发送报文。

        /* set state */ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);/* transmit the first SYN packet */ret = cp->packet_xmit(skb, cp, pd->pp, iph);/* do not touch skb anymore */if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) && cp->control)atomic_inc(&cp->control->in_pkts);elseatomic_inc(&cp->in_pkts);ip_vs_conn_put(cp);return ret;}

以上的条件未满足,如果IPVS虚拟服务指定为FTP服务端口(21),但是当前报文的目的端口不等于21,表明为其它的服务,交由linux内核协议栈进行处理。再者,如果当前报文为ICMP报文,返回NF_DROP。

    /** When the virtual ftp service is presented, packets destined for other services on the VIP may get here (except services* listed in the ipvs table), pass the packets, because it is not ipvs job to decide to drop the packets.*/if (svc->port == FTPPORT && dport != FTPPORT)return NF_ACCEPT;if (unlikely(ip_vs_iph_icmp(iph)))return NF_DROP;

如果执行到ip_vs_leave函数最后,将向客户端发送ICMP的端口不可达消息报文。

    /** Notify the client that the destination is unreachable, and release the socket buffer.* Since it is in IP layer, the TCP socket is not actually created, the TCP RST packet cannot be sent, instead that* ICMP_PORT_UNREACH is sent here no matter it is TCP/UDP. --WZ*/
#ifdef CONFIG_IP_VS_IPV6if (svc->af == AF_INET6) {if (!skb->dev)skb->dev = net->loopback_dev;icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);} else
#endificmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);return NF_DROP;

Bypass模式绑定发送函数

在创建bypass类型的连接时,函数ip_vs_conn_new调用ip_vs_bind_xmit为新创建的连接绑定发送函数。

struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af, const union nf_inet_addr *daddr, __be16 dport, ...)
{/* Bind its packet transmitter */
#ifdef CONFIG_IP_VS_IPV6if (p->af == AF_INET6)ip_vs_bind_xmit_v6(cp);else
#endifip_vs_bind_xmit(cp);

如下,根据连接的转发模式,函数ip_vs_bind_xmit为bypass类型连接绑定了发送函数ip_vs_bypass_xmit。

static inline void ip_vs_bind_xmit(struct ip_vs_conn *cp)
{switch (IP_VS_FWD_METHOD(cp)) {case IP_VS_CONN_F_BYPASS:cp->packet_xmit = ip_vs_bypass_xmit;break;

Bypass发送函数

如同所有的转发模式发送函数,首先查找出口路由,与其它模式不同的是,在调用路由查找函数__ip_vs_get_out_rt时,bypass模式指定了IP_VS_RT_MODE_NON_LOCAL标志,即要求查询到的出口路由一定要是外部目的地址。

/*  * Bypass transmitter* Let packets bypass the destination when the destination is not available, it may be only used in transparent cache cluster.*/
int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{struct iphdr  *iph = ip_hdr(skb);if (__ip_vs_get_out_rt(cp->ipvs, cp->af, skb, NULL, iph->daddr, IP_VS_RT_MODE_NON_LOCAL, NULL, ipvsh) < 0)goto tx_error;ip_send_check(iph);

在报文发送之前,设置忽略禁止分片标志ignore_df,以避免在随后的分片函数ip_fragment中,遇到IP报头设置有DF标志的报文,并且其长度大于MTU,而引发icmp_send函数发送代码为ICMP_FRAG_NEEDED的ICMP报文。最后由函数ip_vs_send_or_cont发送报文。

    /* Another hack: avoid icmp_send in ip_fragment */skb->ignore_df = 1;ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 0);return NF_STOLEN;

内核版本 4.15

IPVS之Bypass转发模式相关推荐

  1. IPVS之NAT转发模式

    如下ipvsadm配置命令: $ ipvsadm -A -t 207.175.44.110:80 -s rr $ ipvsadm -a -t 207.175.44.110:80 -r 192.168. ...

  2. IPVS之隧道转发模式

    如下ipvsadm配置命令: $ ipvsadm -A -t 207.175.44.110:80 -s rr $ ipvsadm -a -t 207.175.44.110:80 -r 192.168. ...

  3. IPVS之路由转发模式

    如下ipvsadm配置命令: $ ipvsadm -A -t 207.175.44.110:80 -s rr $ ipvsadm -a -t 207.175.44.110:80 -r 192.168. ...

  4. 家用路由器支持组播吗_组播分布树及其转发模式

    组播分布树及其转发模式 组播分布树及其转发模式 一.soure tree(源树,最短路径树)-shorted path tree(SPT) 1.基于组播源构建的转发路径 (2.dense-mode-密 ...

  5. 交换机的三种转发模式

    下面是交换机6大工作原理: 1.基于源MAC地址学习 2.基于目标MAC地址转发  3.同一接口可以学习到多个MAC地址  4.同一个MAC地址被多个接口学习到,选择后学习到的接口 5.收到广/组播帧 ...

  6. 就是要你懂负载均衡--lvs和转发模式

    本文希望阐述清楚LVS的各种转发模式,以及他们的工作流程和优缺点,同时从网络包的流转原理上解释清楚优缺点的来由,并结合阿里云的slb来说明优缺点. 如果对网络包是怎么流转的不太清楚,推荐先看这篇基础: ...

  7. 由浅入深玩转华为WLAN—21 漫游系列(8)不同AC之间三层漫游【二层上线+直连式+隧道转发模式,相同VLAN,但不同子网的环境】

    三层漫游数据包的过程(隧道转发模式下) 漫游前数据包的走向 1.STA发送数据报文给HAP 2.HAP通过CAPWAP隧道把报文发送给HAC 3.HAC收到以后把业务报文送给上层设备处理转发 漫游后数 ...

  8. 基于华为WAC双机VRRP热备份下旁挂三层组网隧道转发模式解决方案

    基于华为WAC双机VRRP热备份下旁挂三层组网隧道转发模式解决方案 组网拓扑 方案思路 (1) 本案例是旁挂三层组网,隧道转发模式,AP与WAC之间是CAPWAP隧道,业务数据流量通过CAPWAP隧道 ...

  9. 华为AP+AC本地转发模式配置以及理解

    配置思路: AC的配置: AC的无线配置: AC的接口配置 switch 配置: 按照以上配置配好之后,无线网咯就基本上建立了,我在学习这个的时候总有一些问题很困扰,比如为什么ap是通过dhcp怎么获 ...

  10. 无线WLAN隧道转发模式下数据的封装以及转发过程

    无线WLAN隧道转发模式下数据的封装以及转发过程 实验用的拓扑: AP1.AP2的业务vlan为101.102,管理vlan为100,AR路由器作为DHCP服务器为AP和终端分配IP地址.DNS等信息 ...

最新文章

  1. R语言ggplot2时间序列可视化并在特定日期处添加竖线实战
  2. Javascript是否通过引用传递?
  3. 这群理想主义者,在腾讯用10年做到了畅销榜第一
  4. 06 矩阵计算【动手学深度学习v2】
  5. 如何在Windows、Linux中获取主机的网络信息和公网地址
  6. circle函数用法 turtle_Python绘图库Turtle详细分析
  7. oracle votedisk ocr,Oracle RAC 重建OCR和Votedisk
  8. 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage“提示信息
  9. php -- 取日期
  10. asp.net搜索关键词高亮显示函数
  11. Android TextView 实现文字大小不同和文字颜色不同
  12. SQL Server DATEDIFF() 函数
  13. 《机器学习实战:基于Scikit--Learn、Keras和TensorFlow(第2版)》学习笔记——前言
  14. java dwg转pdf_CAD处理控件Aspose.CAD转换功能演示:使用Java将DWG和DXF文件转换为PDF...
  15. HTMLParser错误解决
  16. oracle数据库greatest函数,ORACLE函数之GREATEST函数详解范例
  17. Racket编程指南——17 创造语言
  18. Excel中去重并只保留最近n次日期/最大最小值的数据
  19. 计算广告:第一章——在线广告综述
  20. Mysql如何添加环境变量(详细教程)

热门文章

  1. NoSQL数据库的介绍、NoSQL的产品、NoSQL数据库的分类等;
  2. istio入门与实战 pdf 下载_Istio实战指南 PDF 下载
  3. 中国姓氏大全(常见508个,罕见740个)
  4. jsp mysql demo_ntko: ntko办公插件使用案例demo使用java+jsp+mysql实现
  5. X5内核视频之问答汇总
  6. [Java]图书管理系统
  7. 百花开放笑声甜_“开源萌宠”庆六一
  8. PHP+node采集58微聊聊天信息
  9. mysql卸载详细教程
  10. numpy和pandas官方文档中文版分享