提交 da241efc 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Pull networking fixes from David Miller:

 1) Fix VSOCK layer handling of context ID changes, from Reilly Grant.

 2) Now that we have a synchronize_net() in netdev_rx_handler_unregister(),
    we can't let any call sites hold locks.  Unfortunately bonding does,
    so we have to drop the rwlock there a little bit earlier, fix from
    Veaceslav Falico.

 3) MAC address setting loop exits one iteration too early in mlx4
    driver, from Yan Burman.

 4) Restore ipv6 routes properly upon ifdown/ifup of loopback, from
    Balakumaran Kannan.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  VSOCK: Handle changes to the VMCI context ID.
  net IPv6 : Fix broken IPv6 routing table after loopback down-up
  cbq: incorrect processing of high limits
  net/mlx4_en: Fix setting initial MAC address
  bonding: get netdev_rx_handler_unregister out of locks
......@@ -1976,12 +1976,11 @@ static int __bond_release_one(struct net_device *bond_dev,
return -EINVAL;
}
write_unlock_bh(&bond->lock);
/* unregister rx_handler early so bond_handle_frame wouldn't be called
* for this slave anymore.
*/
netdev_rx_handler_unregister(slave_dev);
write_unlock_bh(&bond->lock);
synchronize_net();
write_lock_bh(&bond->lock);
if (!all && !bond->params.fail_over_mac) {
......
......@@ -411,8 +411,8 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
static void mlx4_en_u64_to_mac(unsigned char dst_mac[ETH_ALEN + 2], u64 src_mac)
{
unsigned int i;
for (i = ETH_ALEN - 1; i; --i) {
int i;
for (i = ETH_ALEN - 1; i >= 0; --i) {
dst_mac[i] = src_mac & 0xff;
src_mac >>= 8;
}
......
......@@ -2529,6 +2529,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
static void init_loopback(struct net_device *dev)
{
struct inet6_dev *idev;
struct net_device *sp_dev;
struct inet6_ifaddr *sp_ifa;
struct rt6_info *sp_rt;
/* ::1 */
......@@ -2540,6 +2543,30 @@ static void init_loopback(struct net_device *dev)
}
add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
/* Add routes to other interface's IPv6 addresses */
for_each_netdev(dev_net(dev), sp_dev) {
if (!strcmp(sp_dev->name, dev->name))
continue;
idev = __in6_dev_get(sp_dev);
if (!idev)
continue;
read_lock_bh(&idev->lock);
list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
continue;
sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
/* Failure cases are ignored */
if (!IS_ERR(sp_rt))
ip6_ins_rt(sp_rt);
}
read_unlock_bh(&idev->lock);
}
}
static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)
......
......@@ -962,8 +962,11 @@ cbq_dequeue(struct Qdisc *sch)
cbq_update(q);
if ((incr -= incr2) < 0)
incr = 0;
}
q->now += incr;
} else {
if (now > q->now)
q->now = now;
}
q->now_rt = now;
for (;;) {
......
......@@ -207,7 +207,7 @@ static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
struct vsock_sock *vsk;
list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table)
if (vsock_addr_equals_addr_any(addr, &vsk->local_addr))
if (addr->svm_port == vsk->local_addr.svm_port)
return sk_vsock(vsk);
return NULL;
......@@ -220,8 +220,8 @@ static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
list_for_each_entry(vsk, vsock_connected_sockets(src, dst),
connected_table) {
if (vsock_addr_equals_addr(src, &vsk->remote_addr)
&& vsock_addr_equals_addr(dst, &vsk->local_addr)) {
if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
dst->svm_port == vsk->local_addr.svm_port) {
return sk_vsock(vsk);
}
}
......
......@@ -464,19 +464,16 @@ static struct sock *vmci_transport_get_pending(
struct vsock_sock *vlistener;
struct vsock_sock *vpending;
struct sock *pending;
struct sockaddr_vm src;
vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
vlistener = vsock_sk(listener);
list_for_each_entry(vpending, &vlistener->pending_links,
pending_links) {
struct sockaddr_vm src;
struct sockaddr_vm dst;
vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
vsock_addr_init(&dst, pkt->dg.dst.context, pkt->dst_port);
if (vsock_addr_equals_addr(&src, &vpending->remote_addr) &&
vsock_addr_equals_addr(&dst, &vpending->local_addr)) {
pkt->dst_port == vpending->local_addr.svm_port) {
pending = sk_vsock(vpending);
sock_hold(pending);
goto found;
......@@ -739,10 +736,15 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
*/
bh_lock_sock(sk);
if (!sock_owned_by_user(sk) && sk->sk_state == SS_CONNECTED)
if (!sock_owned_by_user(sk)) {
/* The local context ID may be out of date, update it. */
vsk->local_addr.svm_cid = dst.svm_cid;
if (sk->sk_state == SS_CONNECTED)
vmci_trans(vsk)->notify_ops->handle_notify_pkt(
sk, pkt, true, &dst, &src,
&bh_process_pkt);
}
bh_unlock_sock(sk);
......@@ -902,6 +904,9 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work)
lock_sock(sk);
/* The local context ID may be out of date. */
vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
switch (sk->sk_state) {
case SS_LISTEN:
vmci_transport_recv_listen(sk, pkt);
......@@ -958,6 +963,10 @@ static int vmci_transport_recv_listen(struct sock *sk,
pending = vmci_transport_get_pending(sk, pkt);
if (pending) {
lock_sock(pending);
/* The local context ID may be out of date. */
vsock_sk(pending)->local_addr.svm_cid = pkt->dg.dst.context;
switch (pending->sk_state) {
case SS_CONNECTING:
err = vmci_transport_recv_connecting_server(sk,
......
......@@ -64,16 +64,6 @@ bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
}
EXPORT_SYMBOL_GPL(vsock_addr_equals_addr);
bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
const struct sockaddr_vm *other)
{
return (addr->svm_cid == VMADDR_CID_ANY ||
other->svm_cid == VMADDR_CID_ANY ||
addr->svm_cid == other->svm_cid) &&
addr->svm_port == other->svm_port;
}
EXPORT_SYMBOL_GPL(vsock_addr_equals_addr_any);
int vsock_addr_cast(const struct sockaddr *addr,
size_t len, struct sockaddr_vm **out_addr)
{
......
......@@ -24,8 +24,6 @@ bool vsock_addr_bound(const struct sockaddr_vm *addr);
void vsock_addr_unbind(struct sockaddr_vm *addr);
bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
const struct sockaddr_vm *other);
bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
const struct sockaddr_vm *other);
int vsock_addr_cast(const struct sockaddr *addr, size_t len,
struct sockaddr_vm **out_addr);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册