Exemple #1
0
int main(void)
{
  uint8_t data;
  watchdog_stop();
  
  set_mcu_speed_dco_mclk_16MHz_smclk_8MHz();

  led_red_on();
  
  uart_init(UART_9600_SMCLK_8MHZ);
  serial_ring_init();
  uart_register_cb( serial_cb);
  
  printf("serial test application: echo\n");
  led_green_on();
  eint();
  
  for(;;)
    {
      LPM(1);
      
      if (serial_ring_get(&data))
	{
	  putchar(data);
	  led_green_switch();
	}
      else
	{
	  printf("\n\n serial_ring_get() returns 0 : empty ring\n\n");
	  led_red_switch();
	}
    }
}
/* This will foreward the given IP packet 
It checks for the Destination IP address and finds appropriate interface (LPM) and sends out! */
int forward_packet(struct sr_instance* sr,uint8_t* packet,int len,int packet_src_iface)
{
	uint32_t ip;
	sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)packet;
	/* Get Dest IP */
	ip = ip_header->ip_dst;

	/* This target variable stores the next hop */
	struct sr_rt* target = NULL;
	/* Perform LPM and get the target routing table entry which has the interface to pass and next hop IP */
	target = LPM(sr->routing_table,ip);
	/* Now the next hop ip (dest->gw)  is known and the interface also */
	if( target == NULL )
	{
		/* ICMP Destination Unreachable */
		/* There is no routing table entry for this destination IP address
		Now we have to send this packet encapsulated in ICMP packet with 3,0( Destiantion Network Unreachable )
		with src address of the incoming interface address and destination address as the source */
		
		/* We have IP packet, Now encapsulate in the ICMP */
		sr_icmp_hdr_t* ih = (sr_icmp_hdr_t*)(packet+sizeof(sr_ip_hdr_t));
		if( (ip_header->ip_p == ICMP_PROTOCOL) && (ih->icmp_type != 8) )
		{
			/* Dont send an ICMP for ICMP */
			return;
		}
		print_hdr_ip(packet);
		int size = sizeof(sr_ip_hdr_t)+sizeof(sr_icmp_hdr_t)+sizeof(sr_ip_hdr_t)+8;

		uint8_t* complete_packet = (uint8_t*) malloc(sizeof(uint8_t)*size);

		uint8_t* icmp_start = make_ICMP(sr,packet,len,3,0);
		
		
		struct sr_if* src_if = sr_get_interface(sr,packet_src_iface);
		

		uint8_t* ip_start = make_IP_packet(*((uint8_t*)ip_header),(0x0000), htons(size), 0x0000, 0x0000,64,0x01, \
								src_if->ip,ip_header->ip_src);
		
		/* Foreward the ICMP packet with 3,0 to the src host */
		/* If the entry is again wrong, then dont send the ICMP for ICMP */
		
		memcpy(complete_packet,ip_start,sizeof(sr_ip_hdr_t));
		memcpy(complete_packet+sizeof(sr_ip_hdr_t),icmp_start,sizeof(sr_icmp_hdr_t)+sizeof(sr_ip_hdr_t)+8);
		
		forward_packet(sr,complete_packet,size,packet_src_iface);
		return;
	}

	/* Now query for the Ethernet details */
	/* Get the router interface from where the packet should leave */
	struct sr_if* src_interface = sr_get_interface(sr,target->interface);
	/* Get the ARP entry for the next hop IP */
	struct sr_arpentry* entry = sr_arpcache_lookup(&sr->cache,(target->gw.s_addr));
	/* Now build the ethernet header */	
	
	uint8_t* complete_packet = (uint8_t*)malloc(sizeof(sr_ethernet_hdr_t)+len);

	memcpy(complete_packet+sizeof(sr_ethernet_hdr_t),packet,len);	
	
	/* Fill in all the details of the ethernet */

	sr_ethernet_hdr_t* eth_hdr = (sr_ethernet_hdr_t*)complete_packet;
	memcpy(eth_hdr->ether_shost,src_interface->addr,sizeof(uint8_t)*6);
	eth_hdr->ether_type = htons(IP_PROTOCOL);

	/* If entry is NULL, It means that there is no cache entry in ARP Table */
	/* If not NULL, Then use the entry for next hop MAC address */

	/*assert(entry!=NULL);*/
	
	if( entry == NULL )
	{
		/* Destination MAC is not known ! */
		memset(eth_hdr->ether_dhost,0,sizeof(uint8_t)*6);
		/* Cache doesnt have this entry, So request it */
		struct sr_arpreq* req = sr_arpcache_queuereq(&sr->cache,target->gw.s_addr,complete_packet,len+sizeof(sr_ethernet_hdr_t) \
								,target->interface);
		assert(req!=NULL);
		/* Free the packet, as we dont need it. It has been copied to other buffer in the request queue */
		handle_ARP_req(sr, &sr->cache,req);
	}
	else
	{
		/* Destination MAC is known, So use it! */	
		memcpy(eth_hdr->ether_dhost,entry->mac,sizeof(uint8_t)*6);
		/* Now send the packet to the target interface */
		sr_send_packet(sr,complete_packet,sizeof(sr_ethernet_hdr_t)+len,target->interface);
		free(entry);
	}
}