/* Modifies packet as per logical endpoint configuration and egress data format * for egress device configured in logical endpoint. Packet is then transmitted * on the egress device. */ void rmnet_egress_handler(struct sk_buff *skb) { struct net_device *orig_dev; struct rmnet_port *port; struct rmnet_priv *priv; u8 mux_id; sk_pacing_shift_update(skb->sk, 8); orig_dev = skb->dev; priv = netdev_priv(orig_dev); skb->dev = priv->real_dev; mux_id = priv->mux_id; port = rmnet_get_port(skb->dev); if (!port) goto drop; if (rmnet_map_egress_handler(skb, port, mux_id, orig_dev)) goto drop; rmnet_vnd_tx_fixup(skb, orig_dev); dev_queue_xmit(skb); return; drop: this_cpu_inc(priv->pcpu_stats->stats.tx_drops); kfree_skb(skb); }
/** * rmnet_egress_handler() - Egress handler entry point * @skb: packet to transmit * @ep: logical endpoint configuration of the packet originator * (e.g.. RmNet virtual network device) * * Modifies packet as per logical endpoint configuration and egress data format * for egress device configured in logical endpoint. Packet is then transmitted * on the egress device. */ void rmnet_egress_handler(struct sk_buff *skb, struct rmnet_logical_ep_conf_s *ep) { struct rmnet_phys_ep_conf_s *config; struct net_device *orig_dev; int rc; orig_dev = skb->dev; skb->dev = ep->egress_dev; config = (struct rmnet_phys_ep_conf_s *) rcu_dereference(skb->dev->rx_handler_data); if (!config) { LOGD("%s is not associated with rmnet_data", skb->dev->name); kfree_skb(skb); return; } LOGD("Packet going out on %s with egress format 0x%08X", skb->dev->name, config->egress_data_format); if (config->egress_data_format & RMNET_EGRESS_FORMAT_MAP) { switch (rmnet_map_egress_handler(skb, config, ep, orig_dev)) { case RMNET_MAP_CONSUMED: LOGD("%s", "MAP process consumed packet"); return; case RMNET_MAP_SUCCESS: break; default: LOGD("MAP egress failed on packet on %s", skb->dev->name); rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_EGR_MAPFAIL); return; } } if (ep->rmnet_mode == RMNET_EPMODE_VND) rmnet_vnd_tx_fixup(skb, orig_dev); rmnet_print_packet(skb, skb->dev->name, 't'); trace_rmnet_egress_handler(skb); rc = dev_queue_xmit(skb); if (rc != 0) { LOGD("Failed to queue packet for transmission on [%s]", skb->dev->name); } rmnet_stats_queue_xmit(rc, RMNET_STATS_QUEUE_XMIT_EGRESS); }
/* Modifies packet as per logical endpoint configuration and egress data format * for egress device configured in logical endpoint. Packet is then transmitted * on the egress device. */ void rmnet_egress_handler(struct sk_buff *skb) { struct net_device *orig_dev; struct rmnet_port *port; struct rmnet_priv *priv; u8 mux_id; orig_dev = skb->dev; priv = netdev_priv(orig_dev); skb->dev = priv->real_dev; mux_id = priv->mux_id; port = rmnet_get_port(skb->dev); if (!port) { kfree_skb(skb); return; } if (port->egress_data_format & RMNET_EGRESS_FORMAT_MAP) { switch (rmnet_map_egress_handler(skb, port, mux_id, orig_dev)) { case RMNET_MAP_CONSUMED: return; case RMNET_MAP_SUCCESS: break; default: kfree_skb(skb); return; } } rmnet_vnd_tx_fixup(skb, orig_dev); dev_queue_xmit(skb); }