在dpvs上实现ICMP的源进源出

本文介绍了三角路径问题在网络通信中的影响,包括性能下降、安全风险和故障排查困难。在dpvs的fnat模式下,通过分析tcp/udp报文的出向逻辑,发现它们实现了源进源出。针对ICMP,通过修改源码,去除了不必要的路由选择,实现了ICMP报文的源进源出,从而解决了三角路径问题。
摘要由CSDN通过智能技术生成

1. 缘起

  在网络通信中,当一个请求报文从源主机到达目标主机,并经过中间路由器或交换机进行转发时,请求报文进入主机A的路径和响应报文离开主机A的路径可能不同。这种情况下,就会出现所谓的三角路径问题。如下图:
在这里插入图片描述

   具体来说,当一个请求报文进入主机A的路径与响应报文离开主机A的路径不同,可能导致以下问题:

  1. 网络性能不稳定:如果进入主机A的路径与离开主机A的路径存在较大差异,可能会导致网络性能不稳定。例如,进入主机A的路径可能经过高负载的网络链路,而离开主机A的路径可能经过较空闲的链路。这样的差异可能导致请求和响应之间的延迟不一致,影响网络性能和用户体验。

  2. 安全性问题:在某些情况下,网络中的安全策略可能只应用于特定的路径。如果请求报文进入主机A的路径与响应报文离开主机A的路径不同,可能导致安全策略无法完全覆盖所有的路径,从而增加了网络的安全风险。

  3. 问题排查困难:当出现网络故障或问题时,如果请求报文进入主机A的路径与响应报文离开主机A的路径不同,可能增加了故障排查的难度。因为网络管理员需要同时考虑请求和响应的不同路径,以确定问题的根本原因。

为了解决这个问题,可以采取以下措施:

  1. 路由优化:网络管理员可以优化网络的路由配置,使得请求报文进入主机A的路径和响应报文离开主机A的路径尽可能一致。这可以通过路由策略调整、链路负载均衡等方式实现。

  2. 建立对称路径:尽可能建立对称路径,即让请求报文和响应报文经过相同的网络路径。这可以通过协议配置、网络设备设置等手段实现。

  3. 网络监控和故障排查:网络管理员应该使用适当的网络监控工具来监测网络性能和路径信息。当出现问题时,可以通过监控数据和故障排查工具来分析请求和响应的路径差异,并找出问题所在。

  最近,我们在用dpvs的fnat模式的部署测试中,就碰到了三角路径的问题。其原因是由于dpvs设置的默认路由和进来的路由不一致导致的,当时抓包发现tcp和udp报文走的路径和来源路径是一致的,就是所谓的源进源出,而ping报文则不是,dpvs上的出向流量走的是dpvs上面配置的默认路由。我们希望ping报文能够像tcp/udp一样也能够走源进源出的路径。
  下面就以fnat模式来进行分析。

2. 源码分析

   于是对tcp/udp的出向报文发送逻辑进行了分析。经过分析,tcp/udp出向报文是通过xmit_outbound转发到客户端的,由__dp_vs_in函数调用,源码片段如下:

    /* holding the conn, need a "put" later. */
    if (dir == DPVS_CONN_DIR_INBOUND)
        return xmit_inbound(mbuf, prot, conn);
    else
        return xmit_outbound(mbuf, prot, conn);

   如果dir != DPVS_CONN_DIR_INBOUND就表示当前需要转发的数据包是出向流量,于是调用xmit_outbound函数进行数据包的转发。

  再看xmit_outbound的逻辑:

/* return verdict INET_XXX */
static int xmit_outbound(struct rte_mbuf *mbuf,
                         struct dp_vs_proto *prot,
                         struct dp_vs_conn *conn)
{
   
    int err;
    assert(mbuf && prot && conn);

    if (dp_vs_stats_out(conn, mbuf)) {
   
        dp_vs_conn_put(conn);
        return INET_DROP;
    }

    if (!conn->packet_out_xmit) {
   
        RTE_LOG(WARNING, IPVS, "%s: missing out_xmit\n", __func__);
        dp_vs_conn_put(conn);
        return INET_ACCEPT;
    }

    err = conn->packet_out_xmit(prot, conn, mbuf);
    if (err != EDPVS_OK)
        RTE_LOG(DEBUG, IPVS, "%s: fail to out xmit: %d\n", __func__, err);

    dp_vs_conn_put(conn);
    /* always stolen the packet */
    return INET_STOLEN;
}

  这里关键的就是调用了conn->packet_out_xmit进行数据包的转发。而packet_out_xmit函数指针在fnat模式下面对应的是dp_vs_out_xmit_fnat函数,对于ipv4,dp_vs_out_xmit_fnat函数最终调用的是__dp_vs_out_xmit_fnat4来进行数据包的转发。所以我们来看看__dp_vs_out_xmit_fnat4的实现,源码如下:

static int __dp_vs_out_xmit_fnat4(struct dp_vs_proto *proto,
                                  struct dp_vs_conn *conn,
                                  struct rte_mbuf *mbuf)
{
   
    struct flow4 fl4;
    struct ipv4_hdr *iph = ip4_hdr(mbuf);
    struct route_entry *rt;
    int err, mtu;

    if (!fast_xmit_close && !(conn->flags & DPVS_CONN_F_NOFASTXMIT)) {
   
        /* 通过来源端口转发 */
		dp_vs_save_outxmit_info(mbuf, proto, conn);
        if (!dp_vs_fast_outxmit_fnat(AF_INET, proto, conn, mbuf)) {
   
            return EDPVS_OK;
        }
    }

	/* 通过路由转发 */
    /*
     * drop old route. just for safe, because
     * FNAT is PRE_ROUTING, should not have route.
     */
    if (unlikely(mbuf->userdata != NULL))
        route4_put((struct route_entry *)mbuf->userdata);

    memset(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农心语

您的鼓励是我写作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值