Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: niu_txhost_pktgen.vr | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | #include <vera_defines.vrh> | |
36 | #include <ListMacros.vrh> | |
37 | #include "niu_mem.vrh" | |
38 | #include "dmc_memory_map.vri" | |
39 | #include "txc_memory_map.vri" | |
40 | // #include "tx_host_err_defines.vri" | |
41 | #include "niu_error_dfn.vri" | |
42 | ||
43 | #include "niu_dma.vrh" | |
44 | #include "pcg_token.vrh" | |
45 | #include "niu_txtoken.vrh" | |
46 | #include "niu_txcntrl_wd.vrh" | |
47 | #include "niu_tx_pktconfig.vrh" | |
48 | #include "niu_tx_descp.vrh" | |
49 | #include "cMesg.vrh" | |
50 | #include "pgIdgen.vrh" | |
51 | ||
52 | ||
53 | ||
54 | extern CSparseMem SparseMem; | |
55 | extern mbox_class mbox_id; | |
56 | extern Mesg be_msg; | |
57 | ||
58 | extern niu_gen_pio gen_pio_drv; | |
59 | ||
60 | function byte_array DMAChannel::generate_packets(TxPacketGenConfig PktGenConfig,CTxToken TxToken ) { | |
61 | ||
62 | ||
63 | byte_array packets; | |
64 | integer mac_id; | |
65 | integer d; | |
66 | integer token; | |
67 | integer port_id; | |
68 | integer i; | |
69 | CpgToken pgToken; | |
70 | integer LLC_HACK = 1; | |
71 | bit [15:0] llc_length; | |
72 | integer status; | |
73 | ||
74 | ||
75 | ||
76 | ||
77 | if(PktGenConfig.error_info.hosterrors.dma_errors == NACK_PREF_ERROR) { | |
78 | is_nack_pref_err = 1; | |
79 | nack_pref_err_addr = TxToken.xlate_desc_addr; | |
80 | nack_pref_err_pcaddr = TxToken.xlate_desc_addr - 64'h40; | |
81 | } | |
82 | ||
83 | status = SetTxError.set_up_errors(PktGenConfig,TxToken); | |
84 | if(status) do_not_check_packet = 1; | |
85 | ||
86 | mac_id = PktGenConfig.mac_id ; | |
87 | packets = new(); | |
88 | ||
89 | ||
90 | printf(" Generating Packets for DMA id %d , data_length = %d \n",id,PktGenConfig.data_length); | |
91 | if (get_plus_arg (CHECK, "RX_DROP_PKT_CHECK")) { | |
92 | printf("RX_DROP_PKT_CHECK is specified. MAC-SA before replacing 0x%h\n", PktGenConfig.flow.src_node.l2_addr); | |
93 | // modify src address for the drop checker | |
94 | // This is to be used only for loopback cases | |
95 | PktGenConfig.flow.src_node.l2_addr = pgIdgen.getMacSA(PktGenConfig.loop_back_rxdma_num,mac_id); | |
96 | printf("RX_DROP_PKT_CHECK is specified. MAC-SA after replacing 0x%h\n", PktGenConfig.flow.src_node.l2_addr); | |
97 | } else | |
98 | PktGenConfig.flow.src_node.l2_addr = pgIdgen.getMacSA(id,mac_id); | |
99 | ||
100 | // Need some config info which indicates the type of packets to generate | |
101 | pack_gen[mac_id + 8].pkt_gen( PktGenConfig.flow,PktGenConfig.data_length, 3, pgToken, O_WAIT_SEND_FAKE | O_FAKE_OUT ); | |
102 | printf(" data_len - %d \n",pgToken.pack_db.data_length); | |
103 | printf(" header len - %d \n",pgToken.pack_db.header_len[0]); | |
104 | token = pgToken.gId; | |
105 | ||
106 | // Copy header to out_header in pack_db | |
107 | pgToken.pack_db.out_header[mac_id ] = new; | |
108 | pgToken.pack_db.out_header[mac_id ].use_header = 0; | |
109 | pgToken.pack_db.out_header[mac_id ].header[0] = new; | |
110 | pgToken.pack_db.out_header[mac_id ].header_len[0] = pgToken.pack_db.header_len[ pgToken.pack_db.use_hdr ]; | |
111 | ||
112 | ||
113 | ||
114 | for( i = 0; i < pgToken.pack_db.out_header[mac_id ].header_len[0]; i++ ) | |
115 | pgToken.pack_db.out_header[mac_id].header[0].val[i] = | |
116 | pgToken.pack_db.header[ pgToken.pack_db.use_hdr ].val[i]; | |
117 | ||
118 | // NEW PACKET | |
119 | #ifdef MAC_SAT | |
120 | #else | |
121 | packets = new pgToken.buf; | |
122 | #endif | |
123 | TxToken.pgToken = new pgToken; | |
124 | TxToken.pgToken.exp_err = PktGenConfig.err_pkt; | |
125 | ||
126 | if(PktGenConfig.ecc_2biterr_line1) | |
127 | TxToken.pgToken.do_not_check = do_not_check_packet || PktGenConfig.err_pkt; | |
128 | else | |
129 | TxToken.pgToken.do_not_check = do_not_check_packet; | |
130 | ||
131 | TxToken.pgToken.tx_dma_id = id; | |
132 | printf("Err DEBUG ID - %d Flag - %d \n",TxToken.pgToken.gId,do_not_check_packet); | |
133 | printf("Err DEBUG ID - %d Flag - %d \n",TxToken.pgToken.gId,TxToken.pgToken.do_not_check); | |
134 | ||
135 | printf("gen_pkts : value of exp_err %0d\n",TxToken.pgToken.exp_err); | |
136 | ||
137 | ||
138 | ||
139 | ||
140 | printf("################## BEFORE HOSTPKT DISPLAY\n"); | |
141 | ||
142 | if (get_plus_arg(CHECK,"TX_VERBOSE")) { | |
143 | pack_gen[mac_id + 8].display_buf(packets,PktGenConfig.data_length); | |
144 | } | |
145 | ||
146 | ||
147 | if(tx_port_num == -1) { | |
148 | printf("ERROR- TxPort Not Bound for DMA Channel Id -%d \n",id); | |
149 | } else { | |
150 | port_id = tx_port_num; | |
151 | // Only for MAC loop back | |
152 | TxToken.loop_back_rxdma_num = PktGenConfig.loop_back_rxdma_num; | |
153 | TxToken.loop_back_rx_lastpacket = PktGenConfig.loop_back_rx_lastpacket; | |
154 | generate_tokens(port_id,token,TxToken); | |
155 | } | |
156 | ||
157 | generate_packets = packets; | |
158 | ||
159 | } | |
160 | ||
161 | ||
162 | ||
163 | task DMAChannel::gen_txpacket(integer ii,TxPacketGenConfig PktGenConfig) { | |
164 | ||
165 | /* | |
166 | ||
167 | ip_packets = generate_packet(config); | |
168 | ||
169 | noofdescs = check_how_many_descriptors_for_this_packet; | |
170 | for(i=0;i<noofdescs;i++) { | |
171 | get_address(); | |
172 | write_packet_into_memory; | |
173 | create_descriptors; | |
174 | add_descriptors(r); | |
175 | } | |
176 | generate_tokens; | |
177 | ||
178 | */ | |
179 | ||
180 | ||
181 | TxPacketControlWord control_word; | |
182 | CTxdescriptor desc; | |
183 | bit[43:0] address; | |
184 | integer noofdescs; | |
185 | bit [13:0] pkt_length; | |
186 | integer rem_pkt_length; | |
187 | integer i; | |
188 | byte_array packets; | |
189 | bit [127:0] w; | |
190 | byte_array ip_packets; | |
191 | integer pkt_ptr; | |
192 | integer last_pkt_ptr; | |
193 | integer buf_sz; | |
194 | bit [3:0] num_ptr; | |
195 | bit [95:0] debug_mac_hdr_bits; | |
196 | bit [39:0] phy_addr; | |
197 | bit [39:0] desc_phy_addr; | |
198 | bit [39:0] desc_v_addr; | |
199 | bit [39:0] mbox_phy_addr; | |
200 | ||
201 | integer pad; | |
202 | integer mac_id; | |
203 | ||
204 | integer pkt_page_id; | |
205 | integer pageid = -1; // default to give random page_id | |
206 | integer chksum_enb; | |
207 | bit [15:0] partial_chk_sum; | |
208 | bit[43:0] st_addr_4ka; | |
209 | bit[43:0] end_addr_4ka; | |
210 | integer done = 0; | |
211 | integer offset16B = 0; | |
212 | ||
213 | CTxToken TxToken; | |
214 | ||
215 | TxToken = new(); // Uninitialized | |
216 | ||
217 | TxToken.dma_num = id; | |
218 | TxToken.port_num = tx_port_num; | |
219 | ||
220 | pad = PktGenConfig.pad; | |
221 | mac_id = PktGenConfig.mac_id; | |
222 | pkt_length = PktGenConfig.data_length + PktGenConfig.flow.frame.l2_pad_length - 4; | |
223 | ||
224 | TxToken.pkt_length = pkt_length + 2*pad; | |
225 | ||
226 | // get the buffsize from command line | |
227 | ||
228 | if (get_plus_arg (CHECK,"TX_BUFFSZ")) | |
229 | buf_sz = get_plus_arg(NUM,"TX_BUFFSZ"); | |
230 | else | |
231 | buf_sz = 128; | |
232 | ||
233 | // plus arg for a particular page_id | |
234 | ||
235 | if (get_plus_arg (CHECK,"PAGE_ID")) | |
236 | pageid = get_plus_arg(NUM,"PAGE_ID"); | |
237 | ||
238 | if (get_plus_arg (CHECK,"CHKSUM_ENB")) | |
239 | chksum_enb = get_plus_arg(NUM,"CHKSUM_ENB"); | |
240 | else | |
241 | chksum_enb = 0; | |
242 | ||
243 | if(pageid == 0) | |
244 | pkt_page_id = page0_id; | |
245 | else if(pageid == 1) | |
246 | pkt_page_id = page1_id; | |
247 | else { | |
248 | // randomize the pageid | |
249 | pkt_page_id = random()%2 ? page1_id : page0_id; | |
250 | } | |
251 | ||
252 | ||
253 | // based on the gather mode do the following | |
254 | ||
255 | // hack untill clean up happens to code below | |
256 | ||
257 | if((PktGenConfig.gConfig_mode!=0) ) { | |
258 | gen_txGatherPackets( PktGenConfig,pkt_page_id ); | |
259 | } else { | |
260 | ||
261 | ||
262 | if(gather_mode || PktGenConfig.g_mode) { | |
263 | noofdescs = (pkt_length + 16)%buf_sz ? | |
264 | (pkt_length +16)/buf_sz + 1 : | |
265 | (pkt_length + 16)/buf_sz; | |
266 | } else noofdescs = 1; | |
267 | ||
268 | printf("Num of desc used %d\n",noofdescs); | |
269 | ||
270 | num_ptr = noofdescs; | |
271 | TxToken.NoofGathers = noofdescs; | |
272 | ||
273 | for(i=0;i<noofdescs;i++) { | |
274 | ||
275 | done = 0; | |
276 | ||
277 | if (get_plus_arg (CHECK, "USE_RANDOM_ADDRESS")) { | |
278 | if(i==0) { | |
279 | address = SparseMem.get_address(1,pkt_page_id,16);//10Blocks -- 10*block_size = 5120B | |
280 | } else { | |
281 | address = SparseMem.get_address(1,pkt_page_id,64);//10Blocks -- 10*block_size = 5120B | |
282 | } | |
283 | // address = address + 9'h1ff - address[8:0] + 1; | |
284 | // To make this address 64byte aligned | |
285 | } else { | |
286 | address = 44'h0_03456000 + ii*2048 + id*32'h10_0000 + i*buf_sz; | |
287 | } | |
288 | TxToken.xlate_gather_address[i] = SparseMem.xlate_addr( address[39:0], pkt_page_id ); | |
289 | ||
290 | ||
291 | if(i==0) { | |
292 | if( get_plus_arg (CHECK,"ENABLE_MAC_HDR_DEBUG") ) { | |
293 | debug_mac_hdr_bits = gen_debug_header( address, desc_ring.ring_current_addr, pkt_length /*MORE FIELDS TO BE ADDED*/ ); | |
294 | printf(" DEBUG - MAC_ HEADER - %x \n",debug_mac_hdr_bits); | |
295 | ||
296 | PktGenConfig.flow.src_node.l2_addr = debug_mac_hdr_bits[47:0]; | |
297 | PktGenConfig.flow.dst_node.l2_addr = debug_mac_hdr_bits[95:48]; | |
298 | } | |
299 | ||
300 | // get the descriptor virtual & phy address | |
301 | desc_v_addr = desc_ring.ring_start_addr + desc_ring.ring_current_addr; | |
302 | desc_phy_addr = SparseMem.xlate_addr(desc_v_addr,desc_ring.ring_page_id,0); | |
303 | ||
304 | // get ohy address of the mailbox addr | |
305 | mbox_phy_addr = SparseMem.xlate_addr(mailbox_addr,desc_ring.ring_page_id,0); | |
306 | ||
307 | // code to induce pkt_part_err (this is translation erro for pkt_address) | |
308 | // if(PktGenConfig.error_info.hosterrors.packet_errors == PKT_PART_ERROR) | |
309 | if(PktGenConfig.err_code == PKT_PART_ERROR) { | |
310 | address = address ^ 44'hfff_ffff_ffff; | |
311 | do_not_check_packet = 1; | |
312 | TxToken.pgToken.do_not_check = do_not_check_packet; | |
313 | printf("Inducing PKT_PART_ERR\n"); | |
314 | } | |
315 | ||
316 | ||
317 | TxToken.packet_start_address = address; | |
318 | TxToken.descriptor_address = desc_ring.ring_current_addr; | |
319 | TxToken.xlate_desc_addr = desc_phy_addr; | |
320 | TxToken.xlate_mb_addr = mbox_phy_addr; | |
321 | ||
322 | if(noofdescs == 1) | |
323 | TxToken.last_descriptor_address = desc_ring.ring_current_addr; | |
324 | ||
325 | TxToken.print(); | |
326 | ||
327 | ip_packets = generate_packets(PktGenConfig,TxToken); | |
328 | ||
329 | // Check if TCP pkt | |
330 | if((PktGenConfig.flow.frame.frame_class == CL_TCP) || (PktGenConfig.flow.frame.frame_class == CL_TCP_IP_V6) || (PktGenConfig.flow.frame.frame_class == CL_UDP) || (PktGenConfig.flow.frame.frame_class == CL_UDP_IP_V6)) { | |
331 | stuff_psu_hdr_chksum(ip_packets,PktGenConfig); | |
332 | } | |
333 | ||
334 | // display the pseudo hdr stuffed buffer | |
335 | ||
336 | // pack_gen[mac_id + 8].display_buf(ip_packets,PktGenConfig.data_length); | |
337 | } | |
338 | ||
339 | if(i==0) { | |
340 | if(gather_mode || PktGenConfig.g_mode) { | |
341 | ||
342 | control_word = new(i); | |
343 | ||
344 | if(PktGenConfig.set_wrong_ctlwd) | |
345 | w = 128'h0; | |
346 | else | |
347 | w = control_word.format_ctrl_word(PktGenConfig); | |
348 | ||
349 | control_word.set_control_word(w); | |
350 | ||
351 | pkt_ptr = 0; | |
352 | if((pkt_length + 16) <= buf_sz) { | |
353 | if(PktGenConfig.mark_bit) | |
354 | create_descriptor(desc,pkt_length + 16 + 2*pad ,address,num_ptr,1,1,pkt_page_id); | |
355 | else | |
356 | create_descriptor(desc,pkt_length + 16 + 2*pad ,address,num_ptr,1,0,pkt_page_id); | |
357 | ||
358 | TxToken.gather_pkt_length[i] = desc.tr_len; | |
359 | WriteTxControlWord(address,control_word,pkt_page_id); | |
360 | address = address + 16 + pad*2; // 128 bits of internal packet_header | |
361 | WritePackets(ip_packets,address,pkt_length,pkt_ptr,last_pkt_ptr,pkt_page_id); | |
362 | } else { | |
363 | if(PktGenConfig.mark_bit) | |
364 | create_descriptor(desc,buf_sz,address,num_ptr,1,1,pkt_page_id); | |
365 | else | |
366 | create_descriptor(desc,buf_sz,address,num_ptr,1,0,pkt_page_id); | |
367 | TxToken.gather_pkt_length[i] = desc.tr_len; | |
368 | WriteTxControlWord(address,control_word,pkt_page_id); | |
369 | address = address + 16 + pad*2; // 128 bits of internal packet_header | |
370 | WritePackets(ip_packets,address,(buf_sz-16),pkt_ptr,last_pkt_ptr,pkt_page_id); | |
371 | rem_pkt_length = (pkt_length +16) - buf_sz; | |
372 | } | |
373 | desc_ring.add_descriptor(desc); | |
374 | pkt_ptr = last_pkt_ptr; | |
375 | } else { | |
376 | control_word = new(i); | |
377 | pkt_ptr = 0; | |
378 | w = control_word.format_ctrl_word(PktGenConfig); | |
379 | control_word.set_control_word(w); | |
380 | if(PktGenConfig.mark_bit) | |
381 | create_descriptor(desc,pkt_length + 16 + 2*pad ,address,num_ptr,1,1,pkt_page_id); | |
382 | else | |
383 | create_descriptor(desc,pkt_length + 16 + 2*pad ,address,num_ptr,1,0,pkt_page_id); | |
384 | TxToken.gather_pkt_length[i] = desc.tr_len; | |
385 | WriteTxControlWord(address,control_word,pkt_page_id); | |
386 | address = address + 16 + pad*2; | |
387 | WritePackets(ip_packets,address,pkt_length,pkt_ptr,last_pkt_ptr,pkt_page_id); | |
388 | desc_ring.add_descriptor(desc); | |
389 | pkt_ptr = last_pkt_ptr; | |
390 | rem_pkt_length = 0; | |
391 | } | |
392 | } else { | |
393 | if(rem_pkt_length <= buf_sz) { | |
394 | create_descriptor(desc,rem_pkt_length,address,num_ptr,0,0,pkt_page_id); | |
395 | TxToken.gather_pkt_length[i] = desc.tr_len; | |
396 | WritePackets(ip_packets,address,rem_pkt_length,pkt_ptr,last_pkt_ptr,pkt_page_id); | |
397 | rem_pkt_length = rem_pkt_length - buf_sz; | |
398 | // update the last descriptor address of the pkt | |
399 | TxToken.last_descriptor_address = desc_ring.ring_current_addr; | |
400 | printf("last_desc of token %d is %h\n",TxToken.id,TxToken.last_descriptor_address); | |
401 | desc_ring.add_descriptor(desc); | |
402 | PktGenConfig.g_mode = 0; | |
403 | } else { | |
404 | create_descriptor(desc,buf_sz,address,num_ptr,0,0,pkt_page_id); | |
405 | TxToken.gather_pkt_length[i] = desc.tr_len; | |
406 | WritePackets(ip_packets,address,buf_sz,pkt_ptr,last_pkt_ptr,pkt_page_id); | |
407 | rem_pkt_length = rem_pkt_length - buf_sz; | |
408 | desc_ring.add_descriptor(desc); | |
409 | } | |
410 | // printf("Remainder_pkt_len %d\n",rem_pkt_length); | |
411 | pkt_ptr=last_pkt_ptr; | |
412 | } | |
413 | printf("Remainder_pkt_len %d\n",rem_pkt_length); | |
414 | ||
415 | } | |
416 | ||
417 | }// else for hack code | |
418 | } | |
419 | ||
420 | // New code for gather packet generation | |
421 | ||
422 | task DMAChannel::gen_txGatherPackets(TxPacketGenConfig PktGenConfig, (integer pkt_page_id=0)) { | |
423 | ||
424 | ||
425 | ||
426 | TxPacketControlWord control_word; | |
427 | CTxdescriptor desc; | |
428 | bit[43:0] address; | |
429 | integer noofdescs; | |
430 | bit [13:0] pkt_length; | |
431 | integer rem_pkt_length; | |
432 | integer i; | |
433 | byte_array packets; | |
434 | bit [127:0] w; | |
435 | byte_array ip_packets; | |
436 | integer pkt_ptr; | |
437 | integer last_pkt_ptr; | |
438 | integer buf_sz; | |
439 | bit [3:0] num_ptr; | |
440 | bit [3:0] offset; | |
441 | bit [95:0] debug_mac_hdr_bits; | |
442 | integer pad; | |
443 | bit[43:0] st_addr_4ka; | |
444 | ||
445 | ||
446 | CTxToken TxToken; | |
447 | ||
448 | TxToken = new(); // Uninitialized | |
449 | ||
450 | TxToken.dma_num = id; | |
451 | TxToken.port_num = tx_port_num; | |
452 | ||
453 | pad = PktGenConfig.pad; | |
454 | pkt_length = PktGenConfig.data_length + PktGenConfig.flow.frame.l2_pad_length - 4; | |
455 | ||
456 | TxToken.pkt_length = pkt_length + 2*pad; | |
457 | ||
458 | ||
459 | if(PktGenConfig.gConfig_mode == -1) { | |
460 | PktGenConfig.SetGatherFields(); | |
461 | PktGenConfig.printGatherFields(); | |
462 | } | |
463 | noofdescs = PktGenConfig.gConfig_noOfDesc; | |
464 | ||
465 | printf("DMAChannel::gen_txGatherPackets Num of desc to beused %d\n",noofdescs); | |
466 | ||
467 | // ifset in random mode, populate gConfig_length and gConfig_alignment fields | |
468 | ||
469 | ||
470 | num_ptr = noofdescs; | |
471 | TxToken.NoofGathers = noofdescs; | |
472 | for(i=0;i<noofdescs;i++) { | |
473 | ||
474 | if (get_plus_arg (CHECK, "USE_RANDOM_ADDRESS")) { | |
475 | if(i==0) | |
476 | address = SparseMem.get_address(1,pkt_page_id,PktGenConfig.gConfig_alignment[i]);//10Blocks -- 10*block_size = 5120B | |
477 | else { | |
478 | if(PktGenConfig.gConfig_specific_alignment) { | |
479 | st_addr_4ka = SparseMem.get_address(2,pkt_page_id,4096); | |
480 | address = st_addr_4ka + PktGenConfig.gConfig_specific_line*16 +PktGenConfig.gConfig_alignment[i]; | |
481 | } else { | |
482 | ||
483 | address = SparseMem.get_address(1,pkt_page_id,PktGenConfig.gConfig_alignment[i]);//10Blocks -- 10*block_size = 5120B | |
484 | offset = address[3:0]; | |
485 | be_msg.print(e_mesg_info,"niu_tx_descp","gather_waddr_offset","BYTE_ADDR_OFFSET %0h\n",offset); | |
486 | } | |
487 | } | |
488 | ||
489 | // address = address + 9'h1ff - address[8:0] + 1; | |
490 | // To make this address 64byte aligned | |
491 | } | |
492 | ||
493 | TxToken.xlate_gather_address[i] = SparseMem.xlate_addr( address[39:0], pkt_page_id ); | |
494 | ||
495 | ||
496 | if(i==0) { | |
497 | if( get_plus_arg (CHECK,"ENABLE_MAC_HDR_DEBUG") ) { | |
498 | debug_mac_hdr_bits = gen_debug_header( address, desc_ring.ring_current_addr, pkt_length /*MORE FIELDS TO BE ADDED*/ ); | |
499 | printf(" DEBUG - MAC_ HEADER - %x \n",debug_mac_hdr_bits); | |
500 | ||
501 | PktGenConfig.flow.src_node.l2_addr = debug_mac_hdr_bits[47:0]; | |
502 | PktGenConfig.flow.dst_node.l2_addr = debug_mac_hdr_bits[95:48]; | |
503 | } | |
504 | ||
505 | TxToken.packet_start_address = address; | |
506 | TxToken.descriptor_address = desc_ring.ring_current_addr; | |
507 | TxToken.print(); | |
508 | ip_packets = generate_packets(PktGenConfig,TxToken); | |
509 | ||
510 | if(noofdescs == 1) | |
511 | TxToken.last_descriptor_address = desc_ring.ring_current_addr; | |
512 | ||
513 | ||
514 | // Check if TCP pkt | |
515 | if((PktGenConfig.flow.frame.frame_class == CL_TCP) || (PktGenConfig.flow.frame.frame_class == CL_TCP_IP_V6) || (PktGenConfig.flow.frame.frame_class == CL_UDP) || (PktGenConfig.flow.frame.frame_class == CL_UDP_IP_V6)) { | |
516 | stuff_psu_hdr_chksum(ip_packets,PktGenConfig); | |
517 | } | |
518 | ||
519 | } | |
520 | ||
521 | if(i==0) { | |
522 | pkt_ptr = 0; | |
523 | control_word = new(i); | |
524 | w = control_word.format_ctrl_word(PktGenConfig); | |
525 | control_word.set_control_word(w); | |
526 | if(PktGenConfig.mark_bit) | |
527 | create_descriptor(desc,PktGenConfig.gConfig_length[i] + 16 + 2*pad,address,num_ptr,1,1,pkt_page_id); | |
528 | else | |
529 | create_descriptor(desc,PktGenConfig.gConfig_length[i] + 16 + 2*pad,address,num_ptr,1,0,pkt_page_id); | |
530 | TxToken.gather_pkt_length[i] = desc.tr_len; | |
531 | WriteTxControlWord(address,control_word,pkt_page_id); | |
532 | address = address + 16 + 2*pad; // 128 bits of internal packet_header | |
533 | WritePackets(ip_packets,address,PktGenConfig.gConfig_length[i],pkt_ptr,last_pkt_ptr,pkt_page_id); | |
534 | desc_ring.add_descriptor(desc); | |
535 | pkt_ptr = last_pkt_ptr; | |
536 | ||
537 | } else { | |
538 | create_descriptor(desc,PktGenConfig.gConfig_length[i],address,num_ptr,0,0,pkt_page_id); | |
539 | TxToken.gather_pkt_length[i] = desc.tr_len; | |
540 | WritePackets(ip_packets,address,PktGenConfig.gConfig_length[i],pkt_ptr,last_pkt_ptr,pkt_page_id); | |
541 | TxToken.last_descriptor_address = desc_ring.ring_current_addr; | |
542 | printf("last_desc of token %d is %h\n",TxToken.id,TxToken.last_descriptor_address); | |
543 | desc_ring.add_descriptor(desc); | |
544 | PktGenConfig.g_mode = 0; | |
545 | pkt_ptr=last_pkt_ptr; | |
546 | } | |
547 | ||
548 | } | |
549 | ||
550 | } | |
551 | ||
552 | ||
553 | //-- task to calulate partial checksum with zeros in the stuff field | |
554 | ||
555 | function bit[15:0] DMAChannel:: partial_cksum(byte_array ip_packets, TxPacketGenConfig PktGenConfig, integer | |
556 | index) { | |
557 | ||
558 | integer i,j; | |
559 | bit [16:0] chksum_tmp = 16'h0; | |
560 | integer len; | |
561 | integer l4_start; | |
562 | bit [15:0] tmp_pchksum; | |
563 | integer fclass; | |
564 | ||
565 | fclass = PktGenConfig.flow.frame.frame_class; | |
566 | ||
567 | if((fclass == CL_TCP) || (fclass == CL_TCP_IP_V6)) | |
568 | l4_start = index - 16; // this is because index points to the chksum bytes | |
569 | else if((fclass == CL_UDP) || (fclass == CL_UDP_IP_V6)) | |
570 | l4_start = index - 6; // this is because index points to the chksum bytes | |
571 | ||
572 | len = PktGenConfig.data_length + PktGenConfig.flow.frame.l2_pad_length - 4; | |
573 | ||
574 | ip_packets.val[index] = 8'h0; | |
575 | ip_packets.val[index+1] = 8'h0; | |
576 | ||
577 | printf("partial_cksum : index %0d\n",index); | |
578 | printf("partial_cksum : l4_start %0d\n",l4_start); | |
579 | printf("partial_cksum : len %0d\n",len); | |
580 | ||
581 | for(i = l4_start; i < len ; i=i+2) | |
582 | { | |
583 | if(i == len - 1) { | |
584 | chksum_tmp = chksum_tmp + {ip_packets.val[i],8'h0}; | |
585 | chksum_tmp = chksum_tmp + chksum_tmp[16]; | |
586 | chksum_tmp[16] = 1'b0; | |
587 | } else { | |
588 | chksum_tmp = chksum_tmp + {ip_packets.val[i],ip_packets.val[i+1]}; | |
589 | chksum_tmp = chksum_tmp + chksum_tmp[16]; | |
590 | chksum_tmp[16] = 1'b0; | |
591 | } | |
592 | } | |
593 | ||
594 | tmp_pchksum = chksum_tmp[15:0]; | |
595 | ||
596 | partial_cksum = ~({tmp_pchksum[7:0],tmp_pchksum[15:8]}); | |
597 | ||
598 | } | |
599 | ||
600 | ||
601 | ||
602 | //-- task to stuff psuedo header checksum | |
603 | ||
604 | task DMAChannel:: stuff_psu_hdr_chksum(byte_array ip_packets, TxPacketGenConfig PktGenConfig) | |
605 | { | |
606 | ||
607 | integer hdr_len = PktGenConfig.flow.frame.header_length; | |
608 | integer index; | |
609 | integer index_base; | |
610 | bit ipver; | |
611 | bit [15:0] full_chksum; | |
612 | bit [15:0] tmp; | |
613 | ||
614 | bit [15:0] partial_chksum; | |
615 | bit [15:0] psd_hdr_chksum; | |
616 | bit [15:0] inv_psd_hdr_chksum; | |
617 | ||
618 | ipver = PktGenConfig.flow.frame.frame_type[3]; | |
619 | index_base = get_index_base(PktGenConfig); | |
620 | ||
621 | if(ipver == 1'b0) { | |
622 | index = index_base + (hdr_len - 5)*4; | |
623 | } else { | |
624 | index = index_base; | |
625 | } | |
626 | ||
627 | full_chksum = {ip_packets.val[index+1],ip_packets.val[index]}; | |
628 | ||
629 | printf("stuff : full_cksum : value of full_chksum %0h\n",full_chksum); | |
630 | ||
631 | partial_chksum = partial_cksum(ip_packets,PktGenConfig,index); | |
632 | ||
633 | printf("stuff : partial_cksum : value of partial_chksum %0h\n",partial_chksum); | |
634 | ||
635 | if(full_chksum > partial_chksum) | |
636 | psd_hdr_chksum = full_chksum - partial_chksum; | |
637 | else { | |
638 | tmp = full_chksum - 1; | |
639 | psd_hdr_chksum = {1'b1,tmp} - partial_chksum; | |
640 | } | |
641 | ||
642 | ||
643 | printf("stuff : partial_cksum : value of psd_hdr_chksum %0h\n",psd_hdr_chksum); | |
644 | ||
645 | inv_psd_hdr_chksum = ~psd_hdr_chksum; | |
646 | ||
647 | printf("stuff : partial_cksum : value of inv_psd_hdr_chksum %0h\n",inv_psd_hdr_chksum); | |
648 | ||
649 | ip_packets.val[index] = inv_psd_hdr_chksum[7:0]; | |
650 | ip_packets.val[index+1] = inv_psd_hdr_chksum[15:8]; | |
651 | ||
652 | } | |
653 | ||
654 | //--- function to calculate the index base value | |
655 | ||
656 | function integer DMAChannel:: get_index_base(TxPacketGenConfig PktGenConfig) | |
657 | { | |
658 | integer base; | |
659 | integer fclass; | |
660 | bit vlan; | |
661 | bit llc; | |
662 | bit ipver; | |
663 | ||
664 | ipver = PktGenConfig.flow.frame.frame_type[3]; | |
665 | vlan = PktGenConfig.flow.frame.frame_type[2]; | |
666 | llc = PktGenConfig.flow.frame.frame_type[0]; | |
667 | fclass = PktGenConfig.flow.frame.frame_class; | |
668 | ||
669 | if(ipver == 1'b0) { | |
670 | if(fclass == CL_TCP) { | |
671 | case({llc,vlan}) { | |
672 | 2'b00 : base = 50; | |
673 | 2'b01 : base = 54; | |
674 | 2'b10 : base = 58; | |
675 | 2'b11 : base = 62; | |
676 | } | |
677 | } else if(fclass == CL_UDP) { | |
678 | case({llc,vlan}) { | |
679 | 2'b00 : base = 40; | |
680 | 2'b01 : base = 44; | |
681 | 2'b10 : base = 48; | |
682 | 2'b11 : base = 52; | |
683 | } | |
684 | } | |
685 | } else { | |
686 | if(fclass == CL_TCP_IP_V6) { | |
687 | case({llc,vlan}) { | |
688 | 2'b00 : base = 70; | |
689 | 2'b01 : base = 74; | |
690 | 2'b10 : base = 78; | |
691 | 2'b11 : base = 82; | |
692 | } | |
693 | } else if(fclass == CL_UDP_IP_V6) { | |
694 | case({llc,vlan}) { | |
695 | 2'b00 : base = 60; | |
696 | 2'b01 : base = 64; | |
697 | 2'b10 : base = 68; | |
698 | 2'b11 : base = 72; | |
699 | } | |
700 | } | |
701 | } | |
702 | ||
703 | get_index_base = base; | |
704 | } |