| /* |
| * INET An implementation of the TCP/IP protocol suite for the LINUX |
| * operating system. INET is implemented using the BSD Socket |
| * interface as the means of communication with the user level. |
| * |
| * Definitions for the IP protocol. |
| * |
| * Version: @(#)ip.h 1.0.2 04/28/93 |
| * |
| * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version |
| * 2 of the License, or (at your option) any later version. |
| */ |
| #ifndef _LINUX_IP_H |
| #define _LINUX_IP_H |
| |
| #include <linux/skbuff.h> |
| #include <uapi/linux/ip.h> |
| |
| #define QTN_IP_REALIGN_MAX (4) /* Reserve tailroom for realignment on IP header */ |
| #define QTN_IP_REALIGN_BYTES (2) /* realignment bytes on IP header */ |
| |
| static inline struct iphdr *ip_hdr(const struct sk_buff *skb) |
| { |
| return (struct iphdr *)skb_network_header(skb); |
| } |
| |
| static inline struct iphdr *inner_ip_hdr(const struct sk_buff *skb) |
| { |
| return (struct iphdr *)skb_inner_network_header(skb); |
| } |
| |
| static inline struct iphdr *ipip_hdr(const struct sk_buff *skb) |
| { |
| return (struct iphdr *)skb_transport_header(skb); |
| } |
| |
| static inline struct iphdr *ip_hdr_aligned(struct sk_buff *skb) |
| { |
| struct iphdr *iph = ip_hdr(skb); |
| |
| #ifndef CONFIG_QTN_PLATFORM_MISALIGN_WAR |
| int err = 0; |
| |
| if (unlikely(((uint32_t)iph & 0x3) == QTN_IP_REALIGN_BYTES)) { |
| if (unlikely((skb->end - skb->tail) < QTN_IP_REALIGN_BYTES)) { |
| err = pskb_expand_head(skb, 0, QTN_IP_REALIGN_MAX, GFP_ATOMIC); |
| if (err) |
| panic("###### QTN: %s over panic and expand fail\n", __func__); |
| } |
| M_FLAG_SET(skb, M_HAS_MISALIGN); |
| memmove(skb->head + QTN_IP_REALIGN_BYTES, skb->head, skb->end - skb->head - QTN_IP_REALIGN_BYTES); |
| skb->data += QTN_IP_REALIGN_BYTES; |
| skb->tail += QTN_IP_REALIGN_BYTES; |
| skb->mac_header += QTN_IP_REALIGN_BYTES; |
| if (skb->network_header) |
| skb->network_header += QTN_IP_REALIGN_BYTES; |
| if ( skb->transport_header) |
| skb->transport_header += QTN_IP_REALIGN_BYTES; |
| iph = ip_hdr(skb); |
| } |
| #endif |
| |
| return iph; |
| } |
| |
| |
| #endif /* _LINUX_IP_H */ |