Tutorial >> More Plugins | TOC |
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.
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 routine uses three new functions that operate on the shim fields of a packet buffer:
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 |