/** * tipc_l2_send_msg - send a TIPC packet out over an L2 interface * @skb: the packet to be sent * @b: the bearer through which the packet is to be sent * @dest: peer destination address */ int tipc_l2_send_msg(struct net *net, struct sk_buff *skb, struct tipc_bearer *b, struct tipc_media_addr *dest) { struct net_device *dev; int delta; void *tipc_ptr; dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr); if (!dev) return 0; /* Send RESET message even if bearer is detached from device */ tipc_ptr = rcu_dereference_rtnl(dev->tipc_ptr); if (unlikely(!tipc_ptr && !msg_is_reset(buf_msg(skb)))) goto drop; delta = dev->hard_header_len - skb_headroom(skb); if ((delta > 0) && pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) goto drop; skb_reset_network_header(skb); skb->dev = dev; skb->protocol = htons(ETH_P_TIPC); dev_hard_header(skb, dev, ETH_P_TIPC, dest->value, dev->dev_addr, skb->len); dev_queue_xmit(skb); return 0; drop: kfree_skb(skb); return 0; }
/* Returns null if this device is not attached to a datapath. */ struct vport *netdev_get_vport(struct net_device *dev) { #ifdef IFF_BRIDGE_PORT #if IFF_BRIDGE_PORT != IFF_OVS_DATAPATH if (likely(dev->priv_flags & IFF_OVS_DATAPATH)) #else if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook)) #endif return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data); else return NULL; #else return (struct vport *)rcu_dereference_rtnl(dev->br_port); #endif }
/* Returns null if this device is not attached to a datapath. */ struct vport *ovs_netdev_get_vport(struct net_device *dev) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) #if IFF_OVS_DATAPATH != 0 if (likely(dev->priv_flags & IFF_OVS_DATAPATH)) #else if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook)) #endif return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data); else return NULL; #else return (struct vport *)rcu_dereference_rtnl(dev->br_port); #endif }
/* Needs either rcu_read_lock() or rtnl lock */ struct rmnet_port *rmnet_get_port(struct net_device *real_dev) { if (rmnet_is_real_dev_registered(real_dev)) return rcu_dereference_rtnl(real_dev->rx_handler_data); else return NULL; }
/** * tipc_l2_send_msg - send a TIPC packet out over an L2 interface * @buf: the packet to be sent * @b_ptr: the bearer through which the packet is to be sent * @dest: peer destination address */ int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b, struct tipc_media_addr *dest) { struct sk_buff *clone; struct net_device *dev; int delta; dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr); if (!dev) return 0; clone = skb_clone(buf, GFP_ATOMIC); if (!clone) return 0; delta = dev->hard_header_len - skb_headroom(buf); if ((delta > 0) && pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { kfree_skb(clone); return 0; } skb_reset_network_header(clone); clone->dev = dev; clone->protocol = htons(ETH_P_TIPC); dev_hard_header(clone, dev, ETH_P_TIPC, dest->value, dev->dev_addr, clone->len); dev_queue_xmit(clone); return 0; }
/* Returns null if this device is not attached to a datapath. */ struct vport *ovs_netdev_get_vport(struct net_device *dev) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) || \ defined HAVE_RHEL_OVS_HOOK #if IFF_OVS_DATAPATH != 0 if (likely(dev->priv_flags & IFF_OVS_DATAPATH)) #else if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook)) #endif #ifdef HAVE_RHEL_OVS_HOOK return (struct vport *)rcu_dereference_rtnl(dev->ax25_ptr); #else return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data); #endif else return NULL;
static int patch_get_options(const struct vport *vport, struct sk_buff *skb) { struct patch_vport *patch_vport = patch_vport_priv(vport); struct patch_config *patchconf = rcu_dereference_rtnl(patch_vport->patchconf); return nla_put_string(skb, OVS_PATCH_ATTR_PEER, patchconf->peer_name); }
/** * tipc_l2_rcv_msg - handle incoming TIPC message from an interface * @buf: the received packet * @dev: the net device that the packet was received on * @pt: the packet_type structure which was used to register this handler * @orig_dev: the original receive net device in case the device is a bond * * Accept only packets explicitly sent to this node, or broadcast packets; * ignores packets sent using interface multicast, and traffic sent to other * nodes (which can happen if interface is running in promiscuous mode). */ static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { struct tipc_bearer *b_ptr; if (!net_eq(dev_net(dev), &init_net)) { kfree_skb(buf); return NET_RX_DROP; } rcu_read_lock(); b_ptr = rcu_dereference_rtnl(dev->tipc_ptr); if (likely(b_ptr)) { if (likely(buf->pkt_type <= PACKET_BROADCAST)) { buf->next = NULL; tipc_rcv(buf, b_ptr); rcu_read_unlock(); return NET_RX_SUCCESS; } } rcu_read_unlock(); kfree_skb(buf); return NET_RX_DROP; }
/* Returns null if this device is not attached to a datapath. */ struct vport *ovs_netdev_get_vport(struct net_device *dev) { if (likely(dev->priv_flags & IFF_OVS_DATAPATH)) return (struct vport *) rcu_dereference_rtnl(dev->rx_handler_data); else return NULL; }
/* tipc_bearer_send- sends buffer to destination over bearer * * IMPORTANT: * The media send routine must not alter the buffer being passed in * as it may be needed for later retransmission! */ void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf, struct tipc_media_addr *dest) { struct tipc_bearer *b_ptr; rcu_read_lock(); b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); if (likely(b_ptr)) b_ptr->media->send_msg(buf, b_ptr, dest); rcu_read_unlock(); }
void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b; rcu_read_lock(); b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (b) tipc_disc_remove_dest(b->disc); rcu_read_unlock(); }
int tipc_bearer_mtu(struct net *net, u32 bearer_id) { int mtu = 0; struct tipc_bearer *b; rcu_read_lock(); b = rcu_dereference_rtnl(tipc_net(net)->bearer_list[bearer_id]); if (b) mtu = b->mtu; rcu_read_unlock(); return mtu; }
/* tipc_bearer_send- sends buffer to destination over bearer * * IMPORTANT: * The media send routine must not alter the buffer being passed in * as it may be needed for later retransmission! */ void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, struct tipc_media_addr *dest) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; rcu_read_lock(); b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (likely(b_ptr)) b_ptr->media->send_msg(net, buf, b_ptr, dest); rcu_read_unlock(); }
void tipc_bearer_remove_dest(u32 bearer_id, u32 dest) { struct tipc_bearer *b_ptr; rcu_read_lock(); b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); if (b_ptr) { tipc_bcbearer_sort(&b_ptr->nodes, dest, false); tipc_disc_remove_dest(b_ptr->link_req); } rcu_read_unlock(); }
/* tipc_bearer_reset_all - reset all links on all bearers */ void tipc_bearer_reset_all(struct net *net) { struct tipc_net *tn = tipc_net(net); struct tipc_bearer *b; int i; for (i = 0; i < MAX_BEARERS; i++) { b = rcu_dereference_rtnl(tn->bearer_list[i]); if (b) tipc_reset_bearer(net, b); } }
/* Caller must hold RCU or RTNL : * We dont take a reference on found in_device */ struct in_device *inetdev_by_index(struct net *net, int ifindex) { struct net_device *dev; struct in_device *in_dev = NULL; rcu_read_lock(); dev = dev_get_by_index_rcu(net, ifindex); if (dev) in_dev = rcu_dereference_rtnl(dev->ip_ptr); rcu_read_unlock(); return in_dev; }
/* Returns null if this device is not attached to a datapath. */ struct vport *ovs_netdev_get_vport(struct net_device *dev) { #if defined HAVE_NETDEV_RX_HANDLER_REGISTER || \ defined HAVE_RHEL_OVS_HOOK #ifdef HAVE_OVS_DATAPATH if (likely(dev->priv_flags & IFF_OVS_DATAPATH)) #else if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook)) #endif #ifdef HAVE_RHEL_OVS_HOOK return (struct vport *)rcu_dereference_rtnl(dev->ax25_ptr); #else #ifdef HAVE_NET_DEVICE_EXTENDED return (struct vport *) rcu_dereference_rtnl(netdev_extended(dev)->rx_handler_data); #else return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data); #endif #endif else return NULL;
void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; rcu_read_lock(); b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (b_ptr) { tipc_bcbearer_sort(net, &b_ptr->nodes, dest, false); tipc_disc_remove_dest(b_ptr->link_req); } rcu_read_unlock(); }
/* tipc_bearer_xmit_skb - sends buffer to destination over bearer */ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, struct sk_buff *skb, struct tipc_media_addr *dest) { struct tipc_net *tn = tipc_net(net); struct tipc_bearer *b; rcu_read_lock(); b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (likely(b)) b->media->send_msg(net, skb, b, dest); else kfree_skb(skb); rcu_read_unlock(); }
/* tipc_udp_disable - detach bearer from socket */ static void tipc_udp_disable(struct tipc_bearer *b) { struct udp_bearer *ub; ub = rcu_dereference_rtnl(b->media_ptr); if (!ub) { pr_err("UDP bearer instance not found\n"); return; } if (ub->ubsock) sock_set_flag(ub->ubsock->sk, SOCK_DEAD); RCU_INIT_POINTER(ub->bearer, NULL); /* sock_release need to be done outside of rtnl lock */ INIT_WORK(&ub->work, cleanup_bearer); schedule_work(&ub->work); }
static void netvsc_get_stats64(struct net_device *net, struct rtnl_link_stats64 *t) { struct net_device_context *ndev_ctx = netdev_priv(net); struct netvsc_device *nvdev = rcu_dereference_rtnl(ndev_ctx->nvdev); int i; if (!nvdev) return; for (i = 0; i < nvdev->num_chn; i++) { const struct netvsc_channel *nvchan = &nvdev->chan_table[i]; const struct netvsc_stats *stats; u64 packets, bytes, multicast; unsigned int start; stats = &nvchan->tx_stats; do { start = u64_stats_fetch_begin_irq(&stats->syncp); packets = stats->packets; bytes = stats->bytes; } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); t->tx_bytes += bytes; t->tx_packets += packets; stats = &nvchan->rx_stats; do { start = u64_stats_fetch_begin_irq(&stats->syncp); packets = stats->packets; bytes = stats->bytes; multicast = stats->multicast + stats->broadcast; } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); t->rx_bytes += bytes; t->rx_packets += packets; t->multicast += multicast; } t->tx_dropped = net->stats.tx_dropped; t->tx_errors = net->stats.tx_errors; t->rx_dropped = net->stats.rx_dropped; t->rx_errors = net->stats.rx_errors; }
struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) { struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); if (vlan_info) { return vlan_group_get_device(&vlan_info->grp, vlan_id); } else { /* */ if (netif_is_bond_slave(real_dev)) return __vlan_find_dev_deep(real_dev->master, vlan_id); } return NULL; }
/* Must be invoked with rcu_read_lock or with RTNL. */ struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) { struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); if (vlan_info) { return vlan_group_get_device(&vlan_info->grp, vlan_id); } else { /* * Bonding slaves do not have grp assigned to themselves. * Grp is assigned to bonding master instead. */ if (netif_is_bond_slave(real_dev)) return __vlan_find_dev_deep(real_dev->master, vlan_id); } return NULL; }
/* tipc_bearer_xmit() -send buffer to destination over bearer */ void tipc_bearer_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq, struct tipc_media_addr *dst) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b; struct sk_buff *skb, *tmp; if (skb_queue_empty(xmitq)) return; rcu_read_lock(); b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (unlikely(!b)) __skb_queue_purge(xmitq); skb_queue_walk_safe(xmitq, skb, tmp) { __skb_dequeue(xmitq); b->media->send_msg(net, skb, b, dst); }
/** * tipc_l2_send_msg - send a TIPC packet out over an L2 interface * @skb: the packet to be sent * @b: the bearer through which the packet is to be sent * @dest: peer destination address */ int tipc_l2_send_msg(struct net *net, struct sk_buff *skb, struct tipc_bearer *b, struct tipc_media_addr *dest) { struct net_device *dev; int delta; dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr); if (!dev) return 0; delta = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); if ((delta > 0) && pskb_expand_head(skb, delta, 0, GFP_ATOMIC)) { kfree_skb(skb); return 0; } skb_reset_network_header(skb); skb->dev = dev; skb->protocol = htons(ETH_P_TIPC); dev_hard_header(skb, dev, ETH_P_TIPC, dest->value, dev->dev_addr, skb->len); dev_queue_xmit(skb); return 0; }
/* tipc_send_msg - enqueue a send request */ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, struct tipc_bearer *b, struct tipc_media_addr *dest) { int ttl, err = 0; struct udp_bearer *ub; struct udp_media_addr *dst = (struct udp_media_addr *)&dest->value; struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value; struct rtable *rt; if (skb_headroom(skb) < UDP_MIN_HEADROOM) { err = pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC); if (err) goto tx_error; } skb_set_inner_protocol(skb, htons(ETH_P_TIPC)); ub = rcu_dereference_rtnl(b->media_ptr); if (!ub) { err = -ENODEV; goto tx_error; } if (dst->proto == htons(ETH_P_IP)) { struct flowi4 fl = { .daddr = dst->ipv4.s_addr, .saddr = src->ipv4.s_addr, .flowi4_mark = skb->mark, .flowi4_proto = IPPROTO_UDP }; rt = ip_route_output_key(net, &fl); if (IS_ERR(rt)) { err = PTR_ERR(rt); goto tx_error; } skb->dev = rt->dst.dev; ttl = ip4_dst_hoplimit(&rt->dst); udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, dst->ipv4.s_addr, 0, ttl, 0, src->port, dst->port, false, true); #if IS_ENABLED(CONFIG_IPV6) } else { struct dst_entry *ndst; struct flowi6 fl6 = { .flowi6_oif = ub->ifindex, .daddr = dst->ipv6, .saddr = src->ipv6, .flowi6_proto = IPPROTO_UDP }; err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, &ndst, &fl6); if (err) goto tx_error; ttl = ip6_dst_hoplimit(ndst); err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, ndst->dev, &src->ipv6, &dst->ipv6, 0, ttl, 0, src->port, dst->port, false); #endif } return err; tx_error: kfree_skb(skb); return err; } /* tipc_udp_recv - read data from bearer socket */ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb) { struct udp_bearer *ub; struct tipc_bearer *b; ub = rcu_dereference_sk_user_data(sk); if (!ub) { pr_err_ratelimited("Failed to get UDP bearer reference"); kfree_skb(skb); return 0; } skb_pull(skb, sizeof(struct udphdr)); rcu_read_lock(); b = rcu_dereference_rtnl(ub->bearer); if (b) { tipc_rcv(sock_net(sk), skb, b); rcu_read_unlock(); return 0; } rcu_read_unlock(); kfree_skb(skb); return 0; } static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote) { int err = 0; struct ip_mreqn mreqn; struct sock *sk = ub->ubsock->sk; if (ntohs(remote->proto) == ETH_P_IP) { if (!ipv4_is_multicast(remote->ipv4.s_addr)) return 0; mreqn.imr_multiaddr = remote->ipv4; mreqn.imr_ifindex = ub->ifindex; err = ip_mc_join_group(sk, &mreqn); #if IS_ENABLED(CONFIG_IPV6) } else { if (!ipv6_addr_is_multicast(&remote->ipv6)) return 0; err = ipv6_stub->ipv6_sock_mc_join(sk, ub->ifindex, &remote->ipv6); #endif } return err; }
static const unsigned char *patch_get_addr(const struct vport *vport) { const struct patch_vport *patch_vport = patch_vport_priv(vport); return rcu_dereference_rtnl(patch_vport->patchconf)->eth_addr; }
/* Must be called with rcu_read_lock or RTNL lock. */ const char *ovs_dp_name(const struct datapath *dp) { struct vport *vport = rcu_dereference_rtnl(dp->ports[OVSP_LOCAL]); return vport->ops->get_name(vport); }
static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev) { return rcu_dereference_rtnl(dev->mpls_ptr); }
static struct tipc_bearer *bearer_get(struct net *net, int bearer_id) { struct tipc_net *tn = tipc_net(net); return rcu_dereference_rtnl(tn->bearer_list[bearer_id]); }