static void __rmnet_map_ingress_handler(struct sk_buff *skb, struct rmnet_port *port) { struct rmnet_endpoint *ep; u16 len, pad; u8 mux_id; if (RMNET_MAP_GET_CD_BIT(skb)) { if (port->data_format & RMNET_FLAGS_INGRESS_MAP_COMMANDS) return rmnet_map_command(skb, port); goto free_skb; } mux_id = RMNET_MAP_GET_MUX_ID(skb); pad = RMNET_MAP_GET_PAD(skb); len = RMNET_MAP_GET_LENGTH(skb) - pad; if (mux_id >= RMNET_MAX_LOGICAL_EP) goto free_skb; ep = rmnet_get_endpoint(port, mux_id); if (!ep) goto free_skb; skb->dev = ep->egress_dev; /* Subtract MAP header */ skb_pull(skb, sizeof(struct rmnet_map_header)); rmnet_set_skb_proto(skb); if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) { if (!rmnet_map_checksum_downlink_packet(skb, len + pad)) skb->ip_summed = CHECKSUM_UNNECESSARY; } skb_trim(skb, len); rmnet_deliver_skb(skb); return; free_skb: kfree_skb(skb); }
static void __rmnet_map_ingress_handler(struct sk_buff *skb, struct rmnet_port *port) { struct rmnet_endpoint *ep; u8 mux_id; u16 len; if (RMNET_MAP_GET_CD_BIT(skb)) { if (port->ingress_data_format & RMNET_INGRESS_FORMAT_MAP_COMMANDS) return rmnet_map_command(skb, port); goto free_skb; } mux_id = RMNET_MAP_GET_MUX_ID(skb); len = RMNET_MAP_GET_LENGTH(skb) - RMNET_MAP_GET_PAD(skb); if (mux_id >= RMNET_MAX_LOGICAL_EP) goto free_skb; ep = rmnet_get_endpoint(port, mux_id); if (!ep) goto free_skb; skb->dev = ep->egress_dev; /* Subtract MAP header */ skb_pull(skb, sizeof(struct rmnet_map_header)); skb_trim(skb, len); rmnet_set_skb_proto(skb); rmnet_deliver_skb(skb); return; free_skb: kfree_skb(skb); }
/** * 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; }