vowels Plugin

<< Function >>

o Count the number of vowels (i.e., [aeiou]) in the payload of UDP packets.
o The code in handle_pkt_user() contains two counting algorithms:
  1) SCAN_DRAM:  scans DRAM byte-by-byte; and
  2) SCAN_LMEM:  scans "32-byte chunks" in local memory that have been read
  from DRAM.
  See "Methods" section for a description of the slow SCAN_DRAM and faster
  SCAN_LMEM methods.  SCAN_DRAM is the default.
o WARNING:  The plugin doesn't use a callback thread.  So, don't include it
  in the Makefile.

<< Methods >>

o SCAN_DRAM	Let:	q be a ptr to dram
		Then:	access each byte using *q++
o SCAN_LMEM	Let:	q be a ptr to dram that is passed to
				onl_api_ua_8W_read_dram()
			q_lmem be a ptr to a 32-byte (8-word) local memory
				buffer
		Then:

		If q_lmem is aligned on a word boundary
		    Read 8W chunk to local memory and then each local memory
		    	byte using *q_lmem++
		Else
		    Do the same thing but process leading partial chunk first

		Note:  If the payload doesn't begin on a quadword (8 bytes)
			aligned address, only enough bytes are scanned in the
			first chunk so that the next read will occur on a
			quadword boundary.  At worst, this could mean
			wasting the read of 7 bytes at the end of the first
			chunk; i.e., these 7 bytes will be at the front of
			the second chunk.

<< Control Messages >>

Type	Command Semantics			Example
Set	alg= X	Set algorithm to X where 0	IN:  "alg= 1"
		means SCAN_DRAM and anything	OUT: "1"
		else means SCAN_LMEM
Get	=vers	Display version number		IN:  "=vers"
						OUT: "1.3"
Get	=counts	Display counts			IN:  "=counts"
		 (npkts, nbytes, nvowels)	OUT: "1 118 34"
Get	=alg	Display algorithm		IN:  "=alg"
						OUT: "0"
Get	=errno	Display errno[0-4]		IN:  "=errno"
						OUT: "0 0 0 0 0"
Misc	reset	Reset parameters, nbytes[],	IN:  "reset"
		nvowels[], errno[] counters,	OUT: "OK"
		etc.
Misc	debug	toggle debug_on			IN:  "debug"
						OUT: "0"

<< Testing >>

o Use the 'nc' command to send UDP pkts

	server> nc -w 1 -udl 2000			# listen on port 2000
	client> ping -c 3 192.168.2.32		# prime arp tables
	client> nc -w 1 -u 192.168.2.32 2000 < file.in
						# send contents of file.in
						#  (assume n2p1 rcvr) using udp
  - An alternative to ping is to run 1 or 2 experiments to get arp tables primed

o If you omit the "-w 1" argument, nc will not terminate until you enter ctrl-c.
o The input test file was 'file.in', and the output test file was 'file.out'.
o Both algorithms produced the same result.

<< Things To Do >>

o There is a bug that causes the ERR_COUNT (3) plugin counter to get a value
  of 1 or 4 even though there are no errors.  It seems to happen only when
  I call "onl_api_cntr_add((pluginId, VOWEL_COUNT, my_nvowels )" in 
  handle_pkt_user().  All of the other counters seem OK.
o Instead of selecting the algorithm through the control interface ('=alg'),
  you can reduce the memory usage and increase running speed by using
  conditional compilation to select the algorithm.
o I only tested with the simple 1-packet file 'file.in' ...  should test with
  a file that is larger than 1 packet.
o Also, handle TCP packets

<< Lessons Learned >>

o If you don't plan to use a callback thread, change the Makefile to not define
  CALLBACK_THREAD.  If you do include the callback thread, you must have
  callback() sleep or else handle_msg() won't get many cycles and appear to
  be dead.

o onl_api_ua_read_8W_dram() actually reads quadword (8B) chunks and then
  copies out the bytes you requested to be read.  It calls dram_read() to
  do the reading from DRAM.  So, it calls dram_read() to read either 4 or
  5 quadwords depending on whether the address is aligned or not on a
  quadword boundary (4 quadwords is 32 bytes or 8 words).

