| Tutorial >> More Plugins |
|
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 |
|