• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2022 Huawei Device Co., Ltd.
4  *
5  * Description: This file implements the function
6  * of encapsulating the NewIP protocol header.
7  *
8  * Author: Yang Yanjun <yangyanjun@huawei.com>
9  *
10  * Data: 2022-07-18
11  */
12 #include "nip_hdr.h"
13 
14 #define INTEGER_MULTIPLE_OF_8 (~7) /* ~7 is an integer multiple of 8 */
15 #define FMT_FACTORY_NUM_MAX 1
16 #define ENCAP_FACTORY_NUM_MAX 1
17 
nip_calc_pkt_frag_num(unsigned int mtu,unsigned int nip_hdr_len,unsigned int usr_data_len,struct nip_pkt_seg_info * seg_info)18 void nip_calc_pkt_frag_num(unsigned int mtu,
19 			   unsigned int nip_hdr_len,
20 			   unsigned int usr_data_len,
21 			   struct nip_pkt_seg_info *seg_info)
22 {
23 	unsigned int mid_usr_pkt_len = (mtu - nip_hdr_len - NIP_UDP_HDR_LEN) &
24 				       INTEGER_MULTIPLE_OF_8;
25 	unsigned int mid_pkt_num = usr_data_len / mid_usr_pkt_len;
26 	unsigned int last_usr_pkt_len = 0;
27 
28 	if (usr_data_len != 0) {
29 		last_usr_pkt_len = usr_data_len % mid_usr_pkt_len;
30 		if (last_usr_pkt_len == 0) {
31 			last_usr_pkt_len = mid_usr_pkt_len;
32 			mid_pkt_num--;
33 		}
34 	}
35 
36 	seg_info->last_pkt_num = 1;
37 	seg_info->mid_pkt_num = mid_pkt_num;
38 	seg_info->mid_usr_pkt_len = mid_usr_pkt_len;
39 	seg_info->last_usr_pkt_len = last_usr_pkt_len;
40 }
41 
_nip_hdr_ttl_encap(struct nip_hdr_encap * head)42 static inline void _nip_hdr_ttl_encap(struct nip_hdr_encap *head)
43 {
44 	*(head->hdr_buf + head->hdr_buf_pos) = head->ttl;
45 	head->hdr_buf_pos += sizeof(head->ttl);
46 }
47 
_nip_hdr_len_encap(struct nip_hdr_encap * head)48 static inline void _nip_hdr_len_encap(struct nip_hdr_encap *head)
49 {
50 	head->hdr_len_pos = head->hdr_buf + head->hdr_buf_pos;
51 	head->hdr_buf_pos += 1;
52 }
53 
_nip_update_hdr_len(struct nip_hdr_encap * head)54 static inline void _nip_update_hdr_len(struct nip_hdr_encap *head)
55 {
56 	*head->hdr_len_pos = head->hdr_buf_pos;
57 }
58 
_nip_hdr_nexthdr_encap(struct nip_hdr_encap * head)59 static inline void _nip_hdr_nexthdr_encap(struct nip_hdr_encap *head)
60 {
61 	*(head->hdr_buf + head->hdr_buf_pos) = head->nexthdr;
62 	head->hdr_buf_pos += sizeof(head->nexthdr);
63 }
64 
_nip_hdr_daddr_encap(struct nip_hdr_encap * head)65 static inline void _nip_hdr_daddr_encap(struct nip_hdr_encap *head)
66 {
67 	(void)build_nip_addr(&head->daddr, (head->hdr_buf + head->hdr_buf_pos));
68 	head->hdr_buf_pos += (head->daddr.bitlen / NIP_ADDR_BIT_LEN_8);
69 }
70 
_nip_hdr_saddr_encap(struct nip_hdr_encap * head)71 static inline void _nip_hdr_saddr_encap(struct nip_hdr_encap *head)
72 {
73 	(void)build_nip_addr(&head->saddr, (head->hdr_buf + head->hdr_buf_pos));
74 	head->hdr_buf_pos += (head->saddr.bitlen / NIP_ADDR_BIT_LEN_8);
75 }
76 
_nip_hdr_total_len_encap(struct nip_hdr_encap * head)77 static inline void _nip_hdr_total_len_encap(struct nip_hdr_encap *head)
78 {
79 	head->total_len_pos = (unsigned short *)(head->hdr_buf + head->hdr_buf_pos);
80 	head->hdr_buf_pos += sizeof(head->total_len);
81 }
82 
83 /* total_len must be network order.(big end) */
nip_update_total_len(struct nip_hdr_encap * head,unsigned short total_len)84 void nip_update_total_len(struct nip_hdr_encap *head, unsigned short total_len)
85 {
86 	*head->total_len_pos = total_len;
87 }
88 
89 #define BITMAP1_OFFSET 1
90 #define BITMAP2_OFFSET 2
_nip_hdr_encap_udp_bitmap(struct nip_hdr_encap * head)91 static inline void _nip_hdr_encap_udp_bitmap(struct nip_hdr_encap *head)
92 {
93 	/* bitmap(1B) + ttl(1B) + total_len(2B) + nexthdr(1B) + daddr(xB) + saddr(xB) */
94 	/* If the length of the destination address and the source address is even,
95 	 * the length of the packet header must be odd. You need to add 1-byte alignment
96 	 * and 1-byte bitmap
97 	 */
98 	if (((head->daddr.bitlen / NIP_ADDR_BIT_LEN_8) + (head->saddr.bitlen / NIP_ADDR_BIT_LEN_8))
99 	    % NIP_BYTE_ALIGNMENT != 0) {
100 		head->hdr_buf[0] = NIP_UDP_BITMAP_1;
101 		head->hdr_buf_pos = BITMAP1_OFFSET;
102 	} else {
103 		head->hdr_buf[0] = NIP_UDP_BITMAP_1_INC_2;
104 		head->hdr_buf[1] = NIP_NODATA_BITMAP_2;
105 		head->hdr_buf_pos = BITMAP2_OFFSET;
106 	}
107 }
108 
_nip_hdr_encap_comm_bitmap(struct nip_hdr_encap * head)109 static inline void _nip_hdr_encap_comm_bitmap(struct nip_hdr_encap *head)
110 {
111 	/* bitmap(1B) + ttl(1B) + nexthdr(1B) + daddr(xB) + saddr(xB) */
112 	/* If the length of the destination address and the source address is even,
113 	 * the length of the packet header must be odd. You need to add 1-byte alignment
114 	 * and 1-byte bitmap
115 	 */
116 	if (((head->daddr.bitlen / NIP_ADDR_BIT_LEN_8) + (head->saddr.bitlen / NIP_ADDR_BIT_LEN_8))
117 	    % NIP_BYTE_ALIGNMENT != 0) {
118 		head->hdr_buf[0] = NIP_NORMAL_BITMAP_1;
119 		head->hdr_buf_pos = BITMAP1_OFFSET;
120 	} else {
121 		head->hdr_buf[0] = NIP_NORMAL_BITMAP_1_INC_2;
122 		head->hdr_buf[1] = NIP_NODATA_BITMAP_2;
123 		head->hdr_buf_pos = BITMAP2_OFFSET;
124 	}
125 }
126 
127 #define NEWIP_BYTE_ALIGNMENT_ENABLE 1 // 0: disable; 1: enable
128 
nip_hdr_udp_encap(struct nip_hdr_encap * head)129 void nip_hdr_udp_encap(struct nip_hdr_encap *head)
130 {
131 	int len;
132 
133 	if (!head)
134 		return;
135 
136 	len = get_nip_hdr_len(NIP_HDR_UDP, &head->saddr, &head->daddr);
137 	if (len == 0 || len > NIP_HDR_MAX)
138 		return;
139 
140 	/* Encapsulate the bitmap into the newIP packet header BUF */
141 #if (NEWIP_BYTE_ALIGNMENT_ENABLE == 1)
142 	_nip_hdr_encap_udp_bitmap(head);
143 #else
144 	head->hdr_buf[0] = NIP_UDP_BITMAP_1;
145 	head->hdr_buf_pos = 1;
146 #endif
147 
148 	/* Encapsulate bitmap fields into newIP packet header BUF */
149 	_nip_hdr_ttl_encap(head);
150 	_nip_hdr_nexthdr_encap(head);
151 	_nip_hdr_daddr_encap(head);
152 	_nip_hdr_saddr_encap(head);
153 }
154 
155 /* need update total len after this func, call nip_update_total_len */
nip_hdr_comm_encap(struct nip_hdr_encap * head)156 void nip_hdr_comm_encap(struct nip_hdr_encap *head)
157 {
158 	int len;
159 
160 	if (!head)
161 		return;
162 
163 	len = get_nip_hdr_len(NIP_HDR_COMM, &head->saddr, &head->daddr);
164 	if (len == 0 || len > NIP_HDR_MAX)
165 		return;
166 
167 	/* Encapsulate the bitmap into the newIP packet header BUF */
168 #if (NEWIP_BYTE_ALIGNMENT_ENABLE == 1)
169 	_nip_hdr_encap_comm_bitmap(head);
170 #else
171 	head->hdr_buf[0] = NIP_NORMAL_BITMAP_1;
172 	head->hdr_buf_pos = 1;
173 #endif
174 
175 	/* Encapsulate bitmap fields into newIP packet header BUF */
176 	_nip_hdr_ttl_encap(head);
177 	_nip_hdr_total_len_encap(head); /* ARP/TCP need include hdr total len */
178 	_nip_hdr_nexthdr_encap(head);
179 	_nip_hdr_daddr_encap(head);
180 	_nip_hdr_saddr_encap(head);
181 }
182 
183 #if (NEWIP_BYTE_ALIGNMENT_ENABLE == 1)    // include bitmap2
184 #define NIP_COMM_HDR_LEN_NOINCLUDE_ADDR 6 // include total len
185 #define NIP_UDP_HDR_LEN_NOINCLUDE_ADDR  4 // not include total len
186 #else
187 #define NIP_COMM_HDR_LEN_NOINCLUDE_ADDR 5 // include total len
188 #define NIP_UDP_HDR_LEN_NOINCLUDE_ADDR  3 // not include total len
189 #endif
190 /* bitmap1 + bitmap2 + TTL + total len + nexthd + daddr + saddr
191  * 1B        1B        1B    2B          1B       7B      7B    = 20B
192  * NIP_HDR_MAX 20
193  * V4  TCP 1448
194  * NIP TCP 1430 + 30 = 1460
195  */
196 /* The length of the packet header is obtained according to the packet type,
197  * source ADDRESS, and destination address.
198  * If the packet does not carry the source address or destination address, fill in the blank
199  */
get_nip_hdr_len(enum NIP_HDR_TYPE hdr_type,const struct nip_addr * saddr,const struct nip_addr * daddr)200 int get_nip_hdr_len(enum NIP_HDR_TYPE hdr_type,
201 		    const struct nip_addr *saddr,
202 		    const struct nip_addr *daddr)
203 {
204 	int saddr_len = 0;
205 	int daddr_len = 0;
206 	enum NIP_HDR_TYPE base_len = hdr_type == NIP_HDR_UDP ?
207 				     NIP_UDP_HDR_LEN_NOINCLUDE_ADDR :
208 				     NIP_COMM_HDR_LEN_NOINCLUDE_ADDR;
209 
210 	if (hdr_type >= NIP_HDR_TYPE_MAX)
211 		return 0;
212 
213 	if (saddr) {
214 		saddr_len = get_nip_addr_len(saddr);
215 		if (saddr_len == 0)
216 			return 0;
217 	}
218 
219 	if (daddr) {
220 		daddr_len = get_nip_addr_len(daddr);
221 		if (daddr_len == 0)
222 			return 0;
223 	}
224 
225 	return base_len + saddr_len + daddr_len;
226 }
227 
228