The ONL Tutorial

Tutorial >> More Plugins TOC

Copy Packets

The ONL testbed does not recognize multicast IP packets. However, this page describes how to copy and forward a packet to multiple output ports; i.e., multicast a packet at an ingress port. The multicast plugin is installed at an ingress port where it puts copies of a packet into those VOQs corresponding to the desired outputs.

Recall that each packet has a shim prepended to it that carries along information that is used by the FPX. The shim is an intraport shim when it is attached to an IP packet while still in a port processor, and it is an interport shim when it is attached to an IP packet that is transmitted from an input port to an output port.

The multicast_handle_message Function

The variable inst->destVec is a bit vector whose eight rightmost bits indicate with a 1 whether an output port should get a copy of the incoming packet. The bits are scanned from right-to-left as i is iterated through the VOQ numbers 0 to 7. A 1 in the ith position (from the right) indicates that VOQ i should get a copy of the packet.

The destination vector value is initially 0 (indicating no output ports should get a copy), but its value can be set by sending a message to the plugin. Lines 21-29 handle the two messages that add a VOQ and remove a VOQ from the destination vector inst->destVec. For example, in order to add port 3 to the list of output ports that should receive a packet, use the RLI to send a command of 2 and argument of 3 to the plugin instance. This will result in the destination vector being OR'ed with the value of "1<<3" (or 0x8).

 1  int multicast_handle_msg(
 2    struct rp_instance *this,	// pointer to instance structure
 3    void *buf,		// buffer containing integer values
 4    				// buf[0]=instance id
 5    				// buf[1]=command type
 6    				// buf[2]=first parameter value
 7    				// buf[3]=second parameter value ...
 8    u_int8_t flags,		// ignore
 9    u_int8_t seq,		// sequence number of message
10    u_int8_t *len		// number of values in buf
11  ) {
12    struct multicast_instance *inst = (struct multicast_instance *) this;
13    u_int32_t	*vals	= (u_int32_t *) buf;
14    u_int32_t	id 	= (u_int32_t) ntohl(vals[0]);
15    u_int32_t	typ	= (u_int32_t) ntohl(vals[1]);
16    int		i;
17  
18    if (typ == 1) {			// Return destVec
19      vals[0] = (u_int32_t) htonl(inst->destVec);
20      *len = 1*sizeof(u_int32_t);
21    } else if (typ == 2) {		// add VOQ
22      i = ntohl(vals[2]);
23      if (i >= 0 && i < 8) inst->destVec |= 1 << i;
24      *len = 0*sizeof(u_int32_t);
25    } else if (typ == 3) {		// remove VOQ
26      i = ntohl(vals[2]);
27      if (i >= 0 && i < 8) inst->destVec &= ~(1 << i);
28      *len = 0*sizeof(u_int32_t);
29    }
30  
31    return 0;
32  }

The multicast_handle_packet Function

The multicast_handle_packet routine uses three new functions that operate on the shim fields of a packet buffer:

The OVIN field in the intraport shim indicates to the FPX the destination output port (and therefore VOQ).
 1  void copy(char *src, char *dst, int len) {	// Copy len bytes from src to dst.
 2    while (len-- > 0) { *dst++ = *src++; }
 3  }
 4  
 5  void multicast_handle_packet(
 6  	struct rp_instance *this,	// pointer to instance structure
 7  	void *bufferList		// pointer to list of packet buffers
 8  ) {
 9    struct multicast_instance	*inst;
10    msr_bufhdr_t			*buffer, *newBuf;
11    MSR_Shim_t			*shim, *newShim;
12    int				i, first, select, len;
13  
14    inst = (struct multicast_instance *) this;
15    buffer = msr_firstBuffer(bufferList);
16    shim = msr_pkt_shim(buffer);
17  
18    if (inst->destVec == 0) {	// remove packet from input list
19      msr_removeBuffer(bufferList, buffer);     
20      PLUGIN_IPBUF_FREE_FCT(buffer);
21      return;
22    }
23  
24    len = msr_iplen(msr_pkt_iph(buffer));
25    first = 1;
26  
27    for (i = 0, select = 1; i < 8; i++, select <<= 1) {
28      if ((inst->destVec & select) == 0)		continue;
29      if (first == 1) {		// don't need to make a copy
30        first = 0;
31        msr_shim_set_ovin(shim, msr_vin_make(i, 0));	// set VOQ in shim to i
32        continue;
33      }
34      // create copy to send to output i
35      if ((newBuf = PLUGIN_IPBUF_ALLOC_FCT()) == NULL)
36					return; // terminate early if no buffers
37      msr_addBuffer(bufferList, newBuf);
38  
39      // copy original pkt including shim (sets reclassify bit to 0)
40      newShim = msr_pkt_shim(newBuf);
41      copy( (char *) shim, (char *) newShim, len + MSR_FPX_SHIM_SZ);
42      msr_shim_set_ovin(newShim, msr_vin_make(i, 0));	// set VOQ in shim to i
43    }
44  }
The multicast_handle_packet code tour:
  

Tutorial >> More Plugins TOC