/* Processes packet as per ingress data format for receiving device. Logical * endpoint is determined from packet inspection. Packet is then sent to the * egress device listed in the logical endpoint configuration. */ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) { struct sk_buff *skb = *pskb; struct rmnet_port *port; struct net_device *dev; if (!skb) goto done; if (skb->pkt_type == PACKET_LOOPBACK) return RX_HANDLER_PASS; dev = skb->dev; port = rmnet_get_port(dev); switch (port->rmnet_mode) { case RMNET_EPMODE_VND: rmnet_map_ingress_handler(skb, port); break; case RMNET_EPMODE_BRIDGE: rmnet_bridge_handler(skb, port->bridge_ep); break; } done: return RX_HANDLER_CONSUMED; }
/* Processes packet as per ingress data format for receiving device. Logical * endpoint is determined from packet inspection. Packet is then sent to the * egress device listed in the logical endpoint configuration. */ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) { struct sk_buff *skb = *pskb; struct rmnet_port *port; struct net_device *dev; if (!skb) goto done; dev = skb->dev; port = rmnet_get_port(dev); switch (port->rmnet_mode) { case RMNET_EPMODE_VND: if (port->ingress_data_format & RMNET_INGRESS_FORMAT_MAP) rmnet_map_ingress_handler(skb, port); break; case RMNET_EPMODE_BRIDGE: rmnet_bridge_handler(skb, port->bridge_ep); break; } done: return RX_HANDLER_CONSUMED; }
/** * rmnet_ingress_handler() - Ingress handler entry point * @skb: Packet being received * * Processes packet as per ingress data format for receiving device. Logical * endpoint is determined from packet inspection. Packet is then sent to the * egress device listed in the logical endpoint configuration. * * Return: * - RX_HANDLER_PASS if packet is not processed by handler (caller must * deal with the packet) * - RX_HANDLER_CONSUMED if packet is forwarded or processed by MAP */ rx_handler_result_t rmnet_ingress_handler(struct sk_buff *skb) { struct rmnet_phys_ep_conf_s *config; struct net_device *dev; int rc; if (!skb) BUG(); dev = skb->dev; trace_rmnet_ingress_handler(skb); rmnet_print_packet(skb, dev->name, 'r'); 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 RX_HANDLER_CONSUMED; } /* Sometimes devices operate in ethernet mode even thouth there is no * ethernet header. This causes the skb->protocol to contain a bogus * value and the skb->data pointer to be off by 14 bytes. Fix it if * configured to do so */ if (config->ingress_data_format & RMNET_INGRESS_FIX_ETHERNET) { skb_push(skb, RMNET_ETHERNET_HEADER_LENGTH); __rmnet_data_set_skb_proto(skb); } if (config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP) { if (RMNET_MAP_GET_CD_BIT(skb)) { if (config->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_COMMANDS) { rc = rmnet_map_command(skb, config); } else { LOGM("MAP command packet on %s; %s", dev->name, "Not configured for MAP commands"); rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPC); return RX_HANDLER_CONSUMED; } } else { rc = rmnet_map_ingress_handler(skb, config); } } else { switch (ntohs(skb->protocol)) { case ETH_P_MAP: if (config->local_ep.rmnet_mode == RMNET_EPMODE_BRIDGE) { rc = rmnet_ingress_deliver_packet(skb, config); } else { LOGD("MAP packet on %s; MAP not set", dev->name); rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPD); rc = RX_HANDLER_CONSUMED; } break; case ETH_P_ARP: case ETH_P_IP: case ETH_P_IPV6: rc = rmnet_ingress_deliver_packet(skb, config); break; default: LOGD("Unknown skb->proto 0x%04X\n", ntohs(skb->protocol) & 0xFFFF); rc = RX_HANDLER_PASS; } } return rc; }