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