static int rmnet_map_egress_handler(struct sk_buff *skb, struct rmnet_port *port, u8 mux_id, struct net_device *orig_dev) { int required_headroom, additional_header_len; struct rmnet_map_header *map_header; additional_header_len = 0; required_headroom = sizeof(struct rmnet_map_header); if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV4) { additional_header_len = sizeof(struct rmnet_map_ul_csum_header); required_headroom += additional_header_len; } if (skb_headroom(skb) < required_headroom) { if (pskb_expand_head(skb, required_headroom, 0, GFP_ATOMIC)) return -ENOMEM; } if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV4) rmnet_map_checksum_uplink_packet(skb, orig_dev); map_header = rmnet_map_add_map_header(skb, additional_header_len, 0); if (!map_header) return -ENOMEM; map_header->mux_id = mux_id; skb->protocol = htons(ETH_P_MAP); return 0; }
/** * rmnet_map_egress_handler() - MAP egress handler * @skb: Packet being sent * @config: Physical endpoint configuration for the egress device * @ep: logical endpoint configuration of the packet originator * (e.g.. RmNet virtual network device) * @orig_dev: The originator vnd device * * Called if and only if MAP is configured in the egress device's egress data * format. Will expand skb if there is insufficient headroom for MAP protocol. * Note: headroomexpansion will incur a performance penalty. * * Return: * - 0 on success * - 1 on failure */ static int rmnet_map_egress_handler(struct sk_buff *skb, struct rmnet_phys_ep_conf_s *config, struct rmnet_logical_ep_conf_s *ep, struct net_device *orig_dev) { int required_headroom, additional_header_length, ckresult; struct rmnet_map_header_s *map_header; additional_header_length = 0; required_headroom = sizeof(struct rmnet_map_header_s); if ((config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV3) || (config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV4)) { required_headroom += sizeof(struct rmnet_map_ul_checksum_header_s); additional_header_length += sizeof(struct rmnet_map_ul_checksum_header_s); } LOGD("headroom of %d bytes", required_headroom); if (skb_headroom(skb) < required_headroom) { if (pskb_expand_head(skb, required_headroom, 0, GFP_KERNEL)) { LOGD("Failed to add headroom of %d bytes", required_headroom); return 1; } } if ((config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV3) || (config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV4)) { ckresult = rmnet_map_checksum_uplink_packet (skb, orig_dev, config->egress_data_format); trace_rmnet_map_checksum_uplink_packet(orig_dev, ckresult); rmnet_stats_ul_checksum(ckresult); } map_header = rmnet_map_add_map_header(skb, additional_header_length); if (!map_header) { LOGD("%s", "Failed to add MAP header to egress packet"); return 1; } if (config->egress_data_format & RMNET_EGRESS_FORMAT_MUXING) { if (ep->mux_id == 0xff) map_header->mux_id = 0; else map_header->mux_id = ep->mux_id; } skb->protocol = htons(ETH_P_MAP); if (config->egress_data_format & RMNET_EGRESS_FORMAT_AGGREGATION) { rmnet_map_aggregate(skb, config); return RMNET_MAP_CONSUMED; } return RMNET_MAP_SUCCESS; }
static int rmnet_map_egress_handler(struct sk_buff *skb, struct rmnet_port *port, u8 mux_id, struct net_device *orig_dev) { int required_headroom, additional_header_len; struct rmnet_map_header *map_header; additional_header_len = 0; required_headroom = sizeof(struct rmnet_map_header); if (skb_headroom(skb) < required_headroom) { if (pskb_expand_head(skb, required_headroom, 0, GFP_KERNEL)) return RMNET_MAP_CONSUMED; } map_header = rmnet_map_add_map_header(skb, additional_header_len, 0); if (!map_header) return RMNET_MAP_CONSUMED; if (port->egress_data_format & RMNET_EGRESS_FORMAT_MUXING) { if (mux_id == 0xff) map_header->mux_id = 0; else map_header->mux_id = mux_id; } skb->protocol = htons(ETH_P_MAP); return RMNET_MAP_SUCCESS; }