#
#	
#	QoS Implementation
#
#

# Since driver will call using netif_receive_skb, they are in IRQ context
# Need to queue the packet and handle them in interrupt context.
# Otherwise, all packets are handled one by one in rx process.
#
# I implement the ingress QoS must work in interrupt context.
# If the rx is in IRQ context, it will not work properly.
#
# That is, queue the incoming packets to proper queue.
#

IRQ context:
	if(packet is from HOME_IF or from PICO_IF) {
		process_enqueue(skb);
		tasklet_hi_schedule();
		return;
	}

	process_enqueue(skb) {
		queue = classify(skb);
		if(if queue overflow)
			drop(skb);
		else
			enqueue(skb, queue);
	}

Interrupt context:

	tasklet {
		while(1) {
			skb = process_queues();
			if(!skb) {
				if(queue is not empty)
					tasklet_hi_schedule();
				return;
			}
			process_rx();
		}
	}

	process_queues() {
		if(all queues are empty)
			return NULL;
		if(one of Q1, Q2 and Q3 is not empty, and they didn't excess 200kbps) {
			skb = dequeue();
			return skb;
		}	
		if(Q5 is not empty) {
			skb=dequeue(Q5);
			return skb
		}
	}


#
#
#	DHCP Implementation
#
#


# The network packet flow for FemtoCell Project

	DST_MAC = destionation MAC of incoming packet.
	SRC_MAC = source MAC of incoming packet.
	DST_IP = destionation IP of incoming packet.
	SRC_IP = source IP of incoming packet
	L3_PROTO = L3 protocol of incoming packet
	L4_PROTO = L4 ptotocol of incoming packet

	FC_MAC = Device's MAC address of WAN interface
	RG_MAC = Residential Gateway we need to change MAC to
	RG_DEVICE = Residential gateway device.
	DHCPD_IP = The IP address we get from ISP's DHCP server and 
	DHCP_ASSIGNED = If there has a client get our DHCPD_IP, this value will be 1. Otherwise, is 0.


# Packets From WAN_IF:
[Driver]
	If(DHCP_ASSIGNED == 0 || DHCPD_IP == 0)
		Let kernel process this packet
	If(L3_PROTO == ARP && OPMODE = ARP_REPLY && ARP_IP=DHCPD_IP)
		If(ARP_IP == DHCP_IP || ARP_MAC = FC_MAC)
			ARP_REPLY: Copy one instance, one for CPU, the other for peer.
			ARP_REQUEST: for kernel process
		Else
			not our DHCP_IP & FC_MAC, forward to home_if.

	# This should place after all protocol examined is done.
	If(DST_MAC != FC_MAC || DST_MAC == BC_MAC)
		Forward to HOME_IF

	Let kernel process this packet

	-------- NOTE --------
	* ARP packet destined to DHCPD_IP or FC_MAC will be handled by kernel ARP module.
		-> Remote arping WAN_IF: kernel ARP module handles.
		-> Remote arping RG_DEVICE: kernel ARP module replies this request. RG_DEVICE will not receive this request.
		-> RG_DEVICE arping Remote: forward with MAC change. While receiving reply, will copy the original packet. 
									One for kernel and one for RG_DEVICE.
		-> WAN_IF arping Remote: send by kernel. While receiving reply, will copy the original packet. 
									One for kernel and one for RG_DEVICE.

	* If no DHCPD_IP is obtained or no client get this DHCPD_IP from home_if, this packet will be handled by kernel.
	  And this packet will be processed by kernel process. If this packets belongs to a connection of local socket, this 
	  packet will be handled correctly. If this packets doesn't have any conntrack, this packet might be forwarded to dropped.
	

[FW]
	If(no NAT rules)
		If(DHCP_ASSIGNED == 0 || DHCPH_IP == 0)
			Drop this packet silently.
		Else 
			Forward to HOME_IF with MAC change.
	
	-------- NOTE --------
	* Packets will be lookup in PREROUTING chain to see whether there has STATIC NAT RULE. If it has, this packet will
	  be processed by kernel modules ,NAT maybe. Otherwise drop or forward according the DHCPD status.


# Packets From HOME_IF:
[Driver]
	If(DHCPD_IP == 0)
		goto drop_or_process;
	
	If(L4_PROTO == UDP)
		If(This is DHCP related packet)
			If(DHCP_ASSIGNED == 0)
				let dhcp_handler process this packet.
			Else
				If(SRC_MAC == RG_MAC)
					let dhcp_handler process this packet.
				Else
					forward this packet directly.
	
	if(DHCP_ASSIGNED == 0)
		goto drop_or_process;

	If(SRC_MAC != RG_MAC) {
		If(DST_MAC == FC_MAC)
			let kernel process this packet
		If(DST_MAC == BC_MAC)
			clone one instance to CPU.
		forward this packet directly.
	}

	# From here SRC_MAC == RG_MAC
	If(L3_PROTO == ARP)
		forward this packet to WAN_IF with MAC change.
		If(SRC_MAC == RG_MAC)
			modify this packet and forward.
		else
			forward to wan directly

	forward this packet with MAC change.

drop_or_process:
	If(DST_MAC == FC_MAC || DST_MAC == BC_MAC)
		let kernel process this packet
	else
		drop this packet silently.


	-------- NOTE --------
	* Between HOME_IF and WAN_IF, it operates as bridge. That is, we need to forward all packets from HOME_IF to WAN_IF.
	  However, we need take special take of DHCP and ARP packets. And, we also need to change RG_MAC to FC_MAC.
	* To fast the process, I place the DHCP handler in the front of process.

[FW]
	Nothing special



# Packets From PICO_IF:
[Driver]
	let kernel process this packet


[FW]
	Nothing special


