[ovs-dev] Decoding packet_out message

Alvaro Morales Vicente s150682 at student.dtu.dk
Mon Nov 23 14:35:23 UTC 2015


Hi All,

I am really new in OVS. I have problems decoding an ofp_packet_out 
message that my virtual switch receives. Specifically, the packet_out 
message received from the controller is (I get this information from 
wireshark):
  -Header
	-Version: 0x01
	-Type: Packet Out (CSM) (13)
	-Length: 24
	-Transaction ID: 17
  -Packet Out:
	-Buffer ID: 267
	-Frame Recv Port: 1
	-Size of action array in bytes: 8
	-Output Action(s):
		-Type: Output to switch port (0)
		-Len: 8
		-Output port: 1
		-Max bytes to send: 0
		# of Actions: 1

I would like to extract all this fields inside the function 
handle_packet_out() in the ofproto/ofproto.c file. My virtual switch is 
installed on a Raspberry Pi, and I need to know the output port in order 
to transmit the proper signals to an optical switch wired with the 
Raspberry. The handle_packet_out() function is:

handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
{
     struct ofproto *p = ofconn_get_ofproto(ofconn);
     struct ofputil_packet_out po;
     struct dp_packet *payload;
     uint64_t ofpacts_stub[1024 / 8];
     struct ofpbuf ofpacts;
     struct flow flow;
     enum ofperr error;

     COVERAGE_INC(ofproto_packet_out);

     error = reject_slave_controller(ofconn);
     if (error) {
         goto exit;
     }

     /* Decode message. */
     ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
     error = ofputil_decode_packet_out(&po, oh, &ofpacts);
     if (error) {
         goto exit_free_ofpacts;
     }
     if (ofp_to_u16(po.in_port) >= p->max_ports
         && ofp_to_u16(po.in_port) < ofp_to_u16(OFPP_MAX)) {
         error = OFPERR_OFPBRC_BAD_PORT;
         goto exit_free_ofpacts;
     }

     /* Get payload. */
     if (po.buffer_id != UINT32_MAX) {
         error = ofconn_pktbuf_retrieve(ofconn, po.buffer_id, &payload, 
NULL);
         if (error || !payload) {
             goto exit_free_ofpacts;
         }
     } else {
         /* Ensure that the L3 header is 32-bit aligned. */
         payload = dp_packet_clone_data_with_headroom(po.packet, 
po.packet_len, 2);
     }

     /* Verify actions against packet, then send packet if successful. */
     flow_extract(payload, &flow);
     flow.in_port.ofp_port = po.in_port;

     /* Check actions like for flow mods.  We pass a 'table_id' of 0 to
      * ofproto_check_consistency(), which isn't strictly correct because 
these
      * actions aren't in any table.  This is OK as 'table_id' is only 
used to
      * check instructions (e.g., goto-table), which can't appear on the 
action
      * list of a packet-out. */
     error = ofpacts_check_consistency(po.ofpacts, po.ofpacts_len,
                                       &flow, u16_to_ofp(p->max_ports),
                                       0, p->n_tables,
                                       ofconn_get_protocol(ofconn));
     if (!error) {
         error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len);
         if (!error) {
             error = p->ofproto_class->packet_out(p, payload, &flow,
                                                  po.ofpacts, 
po.ofpacts_len);
         }
     }
     dp_packet_delete(payload);

exit_free_ofpacts:
     ofpbuf_uninit(&ofpacts);
exit:
     return error;
}

I can get all the fields except for the actions with the po variable 
(struct ofputil_packet_out) like po.packet_len, po.in_port… I have also 
tried with ofpacts variable (struct ofpbuf) which creates a buffer to 
store the actions list (without success). To sum up, what I need is to 
get the output port as an integer or as a char.

-Struct ofputil_packet_out:

/* Abstract packet-out message.
  *
  * ofputil_decode_packet_out() will ensure that 'in_port' is a physical 
port
  * (OFPP_MAX or less) or one of OFPP_LOCAL, OFPP_NONE, or 
OFPP_CONTROLLER. */
struct ofputil_packet_out {
     const void *packet;         /* Packet data, if buffer_id == 
UINT32_MAX. */
     size_t packet_len;          /* Length of packet data in bytes. */
     uint32_t buffer_id;         /* Buffer id or UINT32_MAX if no buffer. 
*/
     ofp_port_t in_port;         /* Packet's input port. */
     struct ofpact *ofpacts;     /* Actions. */
     size_t ofpacts_len;         /* Size of ofpacts in bytes. */
};

- Struct ofpbuf:

/* Buffer for holding arbitrary data.  An ofpbuf is automatically 
reallocated
  * as necessary if it grows too large for the available memory.
  *
  * 'header' and 'msg' conventions:
  *
  * OpenFlow messages: 'header' points to the start of the OpenFlow
  *    header, while 'msg' is the OpenFlow msg bofy.
  *    When parsing, the 'data' will move past these, as data is being
  *    pulled from the OpenFlow message.
  *
  *    Caution: buffer manipulation of 'struct ofpbuf' must always update
  *             the 'header' and 'msg' pointers.
  *
  *
  * Actions: When encoding OVS action lists, the 'header' is used
  *    as a pointer to the beginning of the current action (see 
ofpact_put()).
  *
  * rconn: Reuses 'header' as a private pointer while queuing.
  */
struct ofpbuf {
     void *base;                 /* First byte of allocated space. */
     void *data;                 /* First byte actually in use. */
     uint32_t size;              /* Number of bytes in use. */
     uint32_t allocated;         /* Number of bytes allocated. */

     void *header;               /* OpenFlow header. */
     void *msg;                  /* message's body */
     struct ovs_list list_node;  /* Private list element for use by 
owner. */
     enum ofpbuf_source source;  /* Source of memory allocated as 'base'. 
*/
};




More information about the dev mailing list