connect EADDRNOTAVAIL (Cannot assign requested address)

 

 目前做反向代理的性能优化时出现 connect 失败, 根据errno 可知, 不能bind当前ip +port;

#define    EADDRNOTAVAIL    99    /* Cannot assign requested address */

参考分析:connect内核代码

int __inet_hash_connect(struct inet_timewait_death_row *death_row,
        struct sock *sk, u32 port_offset,
        int (*check_established)(struct inet_timewait_death_row *,
            struct sock *, __u16, struct inet_timewait_sock **))
{
    struct inet_hashinfo *hinfo = death_row->hashinfo;
    const unsigned short snum = inet_sk(sk)->inet_num;
    struct inet_bind_hashbucket *head;
    struct inet_bind_bucket *tb;
    int ret;
    struct net *net = sock_net(sk);

    if (!snum) {
        int i, remaining, low, high, port;
        static u32 hint;
        u32 offset = hint + port_offset;
        struct inet_timewait_sock *tw = NULL;

        inet_get_local_port_range(net, &low, &high);
        remaining = (high - low) + 1;

        /* By starting with offset being an even number,
         * we tend to leave about 50% of ports for other uses,
         * like bind(0).
         */
        offset &= ~1;

        local_bh_disable();
        for (i = 0; i < remaining; i++) {
            port = low + (i + offset) % remaining;
            if (inet_is_local_reserved_port(net, port))
                continue;
            head = &hinfo->bhash[inet_bhashfn(net, port,
                    hinfo->bhash_size)];
            spin_lock(&head->lock);

            /* Does not bother with rcv_saddr checks,
             * because the established check is already
             * unique enough.
             */
            inet_bind_bucket_for_each(tb, &head->chain) {
                if (net_eq(ib_net(tb), net) &&
                    tb->port == port) {
                    if (tb->fastreuse >= 0 ||
                        tb->fastreuseport >= 0)
                        goto next_port;
                    WARN_ON(hlist_empty(&tb->owners));
                    if (!check_established(death_row, sk,
                                port, &tw))
                        goto ok;
                    goto next_port;
                }
            }

            tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
                    net, head, port);
            if (!tb) {
                spin_unlock(&head->lock);
                break;
            }
            tb->fastreuse = -1;
            tb->fastreuseport = -1;
            goto ok;

        next_port:
            spin_unlock(&head->lock);
        }
        local_bh_enable();

        return -EADDRNOTAVAIL; // 返回错误以及掩码值
}
net.ipv4.ip_local_port_range = 1500     60000

可知是:可选port 不够用, 所以为了提高cps能力, 只能增加后端源ip个数了, 于是使用了ip vlan 增加了4.1.0.2-----4.1.0.10 9个ip地址, 此问题顺利解决。

 

posted @ 2022-11-02 18:47  codestacklinuxer  阅读(96)  评论(0)    收藏  举报