summaryrefslogtreecommitdiffstats
path: root/net/nmrp.c
blob: 3e603fd58dcecb854b9a1d5bce8d7d3d055c5e1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
/*
 *     Copyright (C) 2008 Delta Networks Inc.
 */
#include <common.h>
#include <command.h>
#include <net.h>
//#include "tftp.h"
#include "bootp.h"
#include "nmrp.h"
#include <dni_common.h>

typedef void nmrp_thand_f(void);
ulong NmrpOuripaddr;
ulong NmrpOuripSubnetMask;
ulong NmrpFwOption;
int NmrpFwUPOption = 0;
int NmrpSTUPOption = 0;
int NmrpStringTableUpdateCount = 0;
int NmrpStringTableUpdateIndex = 0;
int NmrpState = 0;
ulong Nmrp_active_start=0;
static ulong NmrpBlock;
static ulong NmrpLastBlock = 0;
int Nmrp_Listen_TimeoutCount = 0;
int Nmrp_REQ_TimeoutCount = 0;
static ulong NmrptimeStart;
static ulong NmrptimeDelta;
static nmrp_thand_f *NmrptimeHandler;
static uchar Nmrpproto;
static int Nmrp_Closing_TimeoutCount = 0;
struct in_addr NmrpClientIP;
uchar NmrpClientEther[6] = { 0, 0, 0, 0, 0, 0 };
uchar NmrpServerEther[6] = { 0, 0, 0, 0, 0, 0 };
static u16 NmrpDevRegionOption = 0;
static uchar NmrpFirmwareFilename[FIRMWARE_FILENAME_LEN] = FIRMWARE_FILENAME;
static u32 NmrpStringTableBitmask = 0;
static uchar NmrpStringTableFilename[STRING_TABLE_FILENAME_LEN] = {0};
static int NmrpStringTableUpdateList[STRING_TABLE_NUMBER_MAX] = {0};
ulong NmrpAliveTimerStart = 0;
ulong NmrpAliveTimerBase = 0;
int NmrpAliveTimerTimeout = NMRP_TIMEOUT_ACTIVE;
int NmrpAliveWaitACK = 0;

static void Nmrp_Listen_Timeout(void);
void NmrpSend(void);

void NmrpStart(void);

void NmrpSetTimeout(unchar, ulong, nmrp_thand_f *);

void Nmrp_Led_Flashing_Timeout();

extern void board_reset_default();

static int MyNetSetEther(volatile uchar * xet, uchar * addr, uint prot)
{
	struct ethernet_hdr *et = (struct ethernet_hdr *) xet;
	ushort myvlanid;
	myvlanid = ntohs(net_our_vlan);
	if (myvlanid == (ushort) - 1)
		myvlanid = VLAN_NONE;
	memcpy(et->et_dest, addr, 6);
    eth_env_get_enetaddr("ethaddr", net_server_ethaddr);
	memcpy(et->et_src, net_server_ethaddr, 6);
	if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
		et->et_protlen = htons(prot);
		return ETHER_HDR_SIZE;
	} else {
		struct vlan_ethernet_hdr *vet =
				(struct vlan_ethernet_hdr *) xet;
		vet->vet_vlan_type = htons(PROT_VLAN);
		vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
		vet->vet_type = htons(prot);
		return VLAN_ETHER_HDR_SIZE;
	}

	return ETHER_HDR_SIZE;
}

static void Nmrp_Conf_Timeout(void)
{
	if (++Nmrp_REQ_TimeoutCount > NMRP_MAX_RETRY_CONF) {
		puts("\n retry conf count exceeded;\n");
		Nmrp_REQ_TimeoutCount = 0;
		NmrpStart();
	} else {
		puts("T");
		NmrpSetTimeout(NMRP_CODE_CONF_ACK,
			       (NMRP_TIMEOUT_REQ * CONFIG_SYS_HZ) / 2,
			       Nmrp_Conf_Timeout);
		NmrpSend();
	}
}

void Nmrp_Closing_Timeout()
{

	if (++Nmrp_Closing_TimeoutCount > NMRP_MAX_RETRY_CLOSE) {
		puts("\n close retry count exceed;stay idle and blink\n");
		Nmrp_Closing_TimeoutCount = 0;
		//board_reset_default(); toso Silver

		puts("\nNMRP is complete. Please switch OFF power.\n");

		Nmrp_Led_Flashing_Timeout();
		/* Unreachable */

		ctrlc();
		console_assign(stdout, "nulldev");
		console_assign(stderr, "nulldev");
		NmrpState = STATE_CLOSED;
		net_set_state(NETLOOP_SUCCESS);
	} else {
		puts("T");
		NmrpSetTimeout(NMRP_CODE_CLOSE_ACK,
			       (CONFIG_SYS_HZ * NMRP_TIMEOUT_REQ) / 2,
			       Nmrp_Closing_Timeout);
		NmrpSend();
	}
}

#define LED_REG_IN_OUT		0xff800500
#define LED_TEST_MASK		0x08000000
#define LED_AL_AH_REG		0xff800528

void board_test_led(int status)
{
	volatile uint32_t *cled_al_ah_reg = (void *)(LED_AL_AH_REG);
	volatile uint32_t *cled_in_out_reg = (void *)(LED_REG_IN_OUT);
	uint32_t val32;

	val32 = *cled_in_out_reg;
	val32 |= LED_TEST_MASK;
	*cled_in_out_reg = val32;

	val32 = *cled_al_ah_reg;
    if( status == 0 )
	    val32 &= ~LED_TEST_MASK;
    else
	    val32 |= LED_TEST_MASK;
	*cled_al_ah_reg = val32;
}

void Nmrp_Led_Flashing_Timeout()
{
	static int NmrpLedCount = 0;
	while (1) {
		NmrpLedCount++;
		if ((NmrpLedCount % 2) == 1) {
			board_test_led(0);
			udelay(500000);
		} else {
			board_test_led(1);
			udelay(500000);
		}
	}
	/* Unreachable */

	/*press ctl+c, turn on test led,then normally boot*/
	board_test_led(0);
}

extern void NmrpSend(void)
{
	volatile u8 *pkt;
	volatile u8 *xp;
	int len = 0;
	int eth_len = 0;
	pkt = (u8 *) net_tx_packet;
	pkt += MyNetSetEther(pkt, NmrpServerEther, PROT_NMRP);
	eth_len = pkt - net_tx_packet;

	switch (NmrpState) {
	case STATE_LISTENING:
		xp = pkt;
		*((u16 *) pkt) = 0;
		pkt += 2;
		*((u8 *) pkt) = (NMRP_CODE_CONF_REQ);
		pkt++;
		*((u8 *) pkt) = 0;
		pkt++;
		*((u16 *) pkt) = htons(6);
		pkt += 2;

		len = pkt - xp;

		(void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
		net_set_timeout_handler((NMRP_TIMEOUT_REQ * CONFIG_SYS_HZ) / 2,
			      Nmrp_Conf_Timeout);
		NmrpSetTimeout(NMRP_CODE_CONF_ACK,
			       (NMRP_TIMEOUT_REQ * CONFIG_SYS_HZ) / 2,
			       Nmrp_Conf_Timeout);
		break;
	case STATE_CONFIGING:
		xp = pkt;
		*((u16 *) pkt) = 0;
		pkt += 2;
		*((u8 *) pkt) = (NMRP_CODE_TFTP_UL_REQ);
		pkt++;
		*((u8 *) pkt) = 0;
		pkt++;
		/* Recv ST-UP option, upgrade string table.
		 * add FILE-NAME option to TFTP-UL-REQ
		 * value of FILE-NAME would like "string table 01"*/
		if (NmrpSTUPOption == 1) {
			/* Append the total length to packet
			 * NMRP_HEADER_LEN for the length of "Reserved", "Code", "Identifier", "Length"
			 * STRING_TABLE_FILENAME_OPT_LEN for the length of "Options". */
			*((u16 *) pkt) = htons((NMRP_HEADER_LEN + STRING_TABLE_FILENAME_OPT_LEN));
			pkt += 2;

			/* Append NMRP option type FILE-NAME */
			*((u16 *) pkt) = htons(NMRP_OPT_FILE_NAME);
			pkt += 2;

			/* Append the total length of NMRP option FILE-NAME */
			*((u16 *) pkt) = htons(STRING_TABLE_FILENAME_OPT_LEN);
			pkt += 2;

			/* Append the string table filename to FILE-NAME option value */
			int i;
			sprintf(NmrpStringTableFilename, "%s%02d", STRING_TABLE_FILENAME_PREFIX,\
				NmrpStringTableUpdateList[NmrpStringTableUpdateIndex]);
			for (i = 0; i < STRING_TABLE_FILENAME_LEN; i++) {
				*((u8 *) pkt) = NmrpStringTableFilename[i];
				pkt++;
			}
			printf("\nReq %s\n", NmrpStringTableFilename);
		/* No string table updates, or all string table updates finished.
		 * And received FW-UP option, upgrading firmware,
		 * add FILE-NAME option to TFTP-UL-REQ */
		} else {
			/* Append the total length to packet
			 * NMRP_HEADER_LEN for the length of "Reserved", "Code", "Identifier", "Length"
			 * STRING_TABLE_FILENAME_OPT_LEN for the length of "Options". */
			*((u16 *) pkt) = htons((NMRP_HEADER_LEN + FIRMWARE_FILENAME_OPT_LEN));
			pkt += 2;

			/* Append NMRP option type FILE-NAME */
			*((u16 *) pkt) = htons(NMRP_OPT_FILE_NAME);
			pkt += 2;

			/* Append the total length of NMRP option FILE-NAME for firmware*/
			*((u16 *) pkt) = htons(FIRMWARE_FILENAME_OPT_LEN);
			pkt += 2;

			/* Append the firmware filename to FILE-NAME option value */
			sprintf(NmrpFirmwareFilename, "%s\n", FIRMWARE_FILENAME);
			int i;
			for (i = 0; i < FIRMWARE_FILENAME_LEN; i++) {
				*((u8 *) pkt) = NmrpFirmwareFilename[i];
				pkt++;
			}
		}
		len = pkt - xp;
		(void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
		int update_table_num = NmrpStringTableUpdateList[NmrpStringTableUpdateIndex];
		if (NmrpSTUPOption == 1)
			UpgradeStringTableFromNmrpServer(update_table_num);
		else
			UpgradeFirmwareFromNmrpServer();
		break;
	case STATE_TFTPUPLOADING:
		printf("TFTP upload done\n");
		NmrpAliveTimerStart = get_timer(0);
		NmrpAliveTimerBase = NMRP_TIMEOUT_ACTIVE / 4;
		NmrpState = STATE_KEEP_ALIVE;
		break;
	case STATE_KEEP_ALIVE:
		printf("NMRP Send Keep alive REQ\n");
		//workaround_ipq40xx_gmac_nmrp_hang_action();
		xp = pkt;
		*((u16 *) pkt) = 0;
		pkt += 2;
		*((u8 *) pkt) = (NMRP_CODE_KEEP_ALIVE_REQ);
		pkt++;
		*((u8 *) pkt) = 0;
		pkt++;
		*((u16 *) pkt) = htons(6);
		pkt += 2;
		len = pkt - xp;
		(void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
		NmrpAliveWaitACK = 1;
		break;
	case STATE_CLOSING:
		printf("NMRP Send Closing REQ\n");
		//workaround_qca8337_gmac_nmrp_hang_action();
		//workaround_ipq40xx_gmac_nmrp_hang_action();
		eth_halt();
        mdelay(1000);
		eth_init();
        mdelay(500);
		xp = pkt;
		*((u16 *) pkt) = 0;
		pkt += 2;
		*((u8 *) pkt) = (NMRP_CODE_CLOSE_REQ);
		pkt++;
		*((u8 *) pkt) = 0;
		pkt++;
		*((u16 *) pkt) = htons(6);
		pkt += 2;
		len = pkt - xp;
		NmrpSetTimeout(NMRP_CODE_CLOSE_ACK, (1 * CONFIG_SYS_HZ),
			       Nmrp_Closing_Timeout);
		(void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
		break;

	case STATE_CLOSED:
		run_command("sdk restoredefault", 0); //board_reset_default();
#if defined(CONFIG_HW29765352P32P4000P512P2X2P2X2P4X4) || \
	defined(CONFIG_HW29765352P0P4096P512P2X2P2X2P4X4) || \
	defined(CONFIG_HW29765515P0P4096P512P2X2P2X2P2X2)
		char runcmd[256];
		printf ("boot_partition_set 1\n");
		snprintf(runcmd, sizeof(runcmd), "boot_partition_set 1");
		run_command(runcmd, 0);
#endif
		NmrptimeHandler=NULL;
		puts("\nNMRP is complete. Please switch OFF power.\n");

		Nmrp_Led_Flashing_Timeout();
		/* Unreachable */

		ctrlc();
		console_assign(stdout, "nulldev");
		console_assign(stderr, "nulldev");
		net_set_state(NETLOOP_SUCCESS);
		break;
	default:
		break;

	}

}

static void Nmrp_Listen_Timeout(void)
{
	if (++Nmrp_Listen_TimeoutCount > NMRP_TIMEOUT_LISTEN) {
		puts("\nRetry count exceeded; boot the image as usual\n");
		Nmrp_Listen_TimeoutCount = 0;
		ResetBootup_usual();
	} else {
		puts("T");
		net_set_timeout_handler(CONFIG_SYS_HZ, Nmrp_Listen_Timeout);
	}
}

static NMRP_PARSED_OPT *Nmrp_Parse(uchar * pkt, ushort optType)
{
	NMRP_PARSED_MSG *msg = (NMRP_PARSED_MSG *) pkt;
	NMRP_PARSED_OPT *opt, *optEnd;
	optEnd = &msg->options[msg->numOptions];
	for (opt = msg->options; opt != optEnd; opt++)
		if (opt->type == ntohs(optType))
			break;
	return msg->numOptions == 0 ? NULL : (opt == optEnd ? NULL : opt);
}

void NmrpSetTimeout(unchar proto, ulong iv, nmrp_thand_f * f)
{
	if (iv == 0) {
		NmrptimeHandler = (nmrp_thand_f *) 0;
		Nmrpproto = 0;
	} else {

		NmrptimeHandler = f;
		NmrptimeStart = get_timer(0);
		NmrptimeDelta = iv;
		Nmrpproto = proto;
	}
}
/*
  Function to parse the NMRP options inside packet.
  If all options are parsed correctly, it returns 0.
 */
static int Nmrp_Parse_Opts(uchar *pkt, NMRP_PARSED_MSG *nmrp_parsed)
{
	nmrp_t *nmrphdr= (nmrp_t*) pkt;
	NMRP_OPT *nmrp_opt;
	int remain_len, opt_index = 0;

	nmrp_parsed->reserved = nmrphdr->reserved;
	nmrp_parsed->code     = nmrphdr->code;
	nmrp_parsed->id       = nmrphdr->id;
	nmrp_parsed->length   = nmrphdr->length;

	remain_len = ntohs(nmrphdr->length) - NMRP_HDR_LEN;

	nmrp_opt = &nmrphdr->opt;
	while (remain_len > 0){
		memcpy(&nmrp_parsed->options[opt_index], nmrp_opt, ntohs(nmrp_opt->len));
		remain_len -= ntohs(nmrp_opt->len);
		nmrp_opt = ((uchar *)nmrp_opt) + ntohs(nmrp_opt->len);
		opt_index++;
	}
	nmrp_parsed->numOptions=opt_index;
	return remain_len;
}

void string_table_bitmask_check()
{
	int update_bit;

	/* find string tables need to be update, begin with smallest bit */
	for (update_bit = 0; update_bit < STRING_TABLE_BITMASK_LEN; update_bit++) {
		if ((NmrpStringTableBitmask & (1 << update_bit)) != 0) {
			//if bit 0 is set, update ST 1, ... etc
			NmrpStringTableUpdateList[NmrpStringTableUpdateCount] = update_bit + 1;
			NmrpStringTableUpdateCount++;
		}
	}
}

void set_region(u16 RegionOption)
{
	uchar region[8];
	sprintf(region, "%04x", RegionOption);
	env_set("region", region);
	run_command("saveenv", 0);
}

void NmrpHandler(uchar * pkt, unsigned dest, struct in_addr src_ip, unsigned src,
                 unsigned type)
{
	nmrp_t *nmrphdr= (nmrp_t*) pkt;
	uchar proto;
	unchar *xp = pkt;
	int fwUpgrade;
	NMRP_PARSED_MSG nmrp_parsed;
	NMRP_PARSED_OPT *opt;
	proto = nmrphdr->code;
	if (type!=PROT_NMRP)
		return;

	/* check for timeout,and run the timeout handler
	   if we have one
	 */

	if (NmrptimeHandler && ((get_timer(0) - NmrptimeStart) > NmrptimeDelta)
	    && (proto != Nmrpproto)) {
		nmrp_thand_f *x;
		x = NmrptimeHandler;
		NmrptimeHandler = (nmrp_thand_f *) 0;
		(*x) ();
	}

	/*
	   Check if Reserved field is zero. Per the specification, the reserved
	   must be all zero in a valid NMRP packet.
	 */
	if (nmrphdr->reserved != 0){
		return;
	}
	memset(&nmrp_parsed, 0, sizeof(NMRP_PARSED_MSG));

	/*
	   Parse the options inside the packet and save it into nmrp_parsed for
	   future reference.
	 */
	if (Nmrp_Parse_Opts(pkt, &nmrp_parsed) != 0){
		/* Some wrong inside the packet, just discard it */
		return;
	}

	NmrpBlock = proto;

	// ignore same packet
	if (NmrpBlock == NmrpLastBlock)
		return;
	NmrpLastBlock = NmrpBlock;

	switch (proto) {
	case NMRP_CODE_ADVERTISE:	/*listening state * */
		if (NmrpState == 0) {
			/*
			   Check if we get the MAGIC-NO option and the content is match
			   with the MAGICNO.
			 */
			if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_MAGIC_NO)) != NULL){
				int opt_hdr_len = sizeof(opt->type) + sizeof(opt->len);
				if (memcmp(opt->value.magicno, MAGICNO, ntohs(opt->len) - opt_hdr_len) == 0){
					NmrpState = STATE_LISTENING;
					board_test_led(0);
					printf("\nNMRP CONFIGING");
					NmrpSend();
				}
			}
		}
		break;
	case NMRP_CODE_CONF_ACK:
		if (NmrpState == STATE_LISTENING) {
			/*
			   If there is no DEV-IP option inside the packet, it must be
			   something wrong in the packet, so just ignore this packet
			   without any action taken.
			 */
			if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_DEV_IP)) != NULL){
				memcpy(NetOurTftpIP, opt->value.ip.addr,IP_ADDR_LEN);
				/* Do we need the subnet mask? */
				memcpy(&NmrpOuripSubnetMask, opt->value.ip.mask,IP_ADDR_LEN);
				/*
				   FW-UP option is optional for CONF-ACK and it has no effect no
				   matter what is the content of this option, so we just skip the
				   process of this option for now, and will add it back when
				   this option is defined as mandatory.
				   The process for FW-UP would be similar as the action taken for
				   DEV-IP and MAGIC-NO.
				 */

				/*When NMRP Client get CONF-ACK with DEV-REGION option*/
				if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_DEV_REGION)) != NULL) {
					/* Save DEV-REGION value to board */
					printf("Get DEV-REGION option, value:0x%04x\n", opt->value.region);
					NmrpDevRegionOption = ntohs(opt->value.region);
					printf("Write Region Number 0x%04x to board\n", NmrpDevRegionOption);
					set_region(NmrpDevRegionOption);
				}
				/*Check if NMRP Client get CONF-ACK with FW-UP option*/
				if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_FW_UP)) != NULL) {
					printf("\nRecv FW-UP option\n");
					NmrpFwUPOption = 1;
				} else {
					printf("\nNo FW-UP option\n");
					NmrpFwUPOption = 0;
				}

				/*When NMRP Client get CONF-ACK with ST-UP option*/
				if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_ST_UP)) != NULL) {
					printf("\nRecv ST-UP option\n");
					NmrpSTUPOption = 1;
					/* Reset string tables' update related variables. */
					NmrpStringTableUpdateCount = 0;
					NmrpStringTableUpdateIndex = 0;
					memset(NmrpStringTableUpdateList, 0,\
						sizeof(NmrpStringTableUpdateList));

					/* Save from network byte-order to host byte-order. */
					NmrpStringTableBitmask = ntohl(opt->value.string_table_bitmask);

					string_table_bitmask_check();
					printf("\nTotal %d String Table need updating\n",\
						NmrpStringTableUpdateCount);
				} else {
					printf("\nNo ST-UP option\n");
					NmrpSTUPOption = 0;
				}
				if (NmrpFwUPOption == 0 && NmrpSTUPOption == 0) {
					NmrpState = STATE_CLOSING;
					printf("\nNo firmware update, nor string table update\n");
					NmrpSend();
				} else {
					NmrpState = STATE_CONFIGING;
					printf("\nNMRP WAITING FOR UPLOAD FIRMWARE or STRING TABLES!\n");
					NmrpSend();
				}
			}else
				break;
		}
		break;
	case NMRP_CODE_KEEP_ALIVE_ACK:
		if (NmrpState == STATE_KEEP_ALIVE) {
			if (NmrpAliveWaitACK == 1) {
				NmrpAliveTimerBase += NMRP_TIMEOUT_ACTIVE / 4;
				NmrpAliveWaitACK = 0;
			}
		}
		break;
	case NMRP_CODE_CLOSE_ACK:
		if (NmrpState == STATE_CLOSING) {
			NmrpState = STATE_CLOSED;
			printf("\nNMRP CLOSED");
			NmrpSend();
		}
		break;
	default:
		break;
	}

}

void NmrpStart(void)
{
	printf("\n Client starts...[Listening] for ADVERTISE...");

	net_set_timeout_handler(CONFIG_SYS_HZ / 10, Nmrp_Listen_Timeout);
	net_set_udp_handler(NmrpHandler);

	NmrpState = 0;
	Nmrp_Listen_TimeoutCount = 0;
	memset(NmrpClientEther, 0, 6);
	NmrpClientIP.s_addr = 0;
}