On Mon, Dec 02, 2013 at 01:20:20PM -0800, Ben Pfaff wrote:
> Signed-off-by: Ben Pfaff <b...@nicira.com>

Reviewed-by: Simon Horman <ho...@verge.net.au>

> ---
>  DESIGN                          |   47 
> +++++++++++++++++++++++++++++++++++++++
>  include/openflow/openflow-1.1.h |    7 +-----
>  lib/ofp-util.c                  |   41 +++++++++++++++++++++++++++++++++-
>  tests/ofp-print.at              |   15 +++++++++++++
>  tests/ofproto.at                |   33 +++++++++++++++++++++++++++
>  5 files changed, 136 insertions(+), 7 deletions(-)
> 
> diff --git a/DESIGN b/DESIGN
> index d36b025..4d654d0 100644
> --- a/DESIGN
> +++ b/DESIGN
> @@ -266,6 +266,53 @@ OpenFlow 1.3 makes these changes:
>  The table for 1.3 is the same as the one shown above for 1.2.
>  
>  
> +OFPT_PACKET_IN
> +==============
> +
> +The OpenFlow 1.1 specification for OFPT_PACKET_IN is confusing.  The
> +definition in OF1.1 openflow.h is[*]:
> +
> +  /* Packet received on port (datapath -> controller). */
> +  struct ofp_packet_in {
> +      struct ofp_header header;
> +      uint32_t buffer_id;     /* ID assigned by datapath. */
> +      uint32_t in_port;       /* Port on which frame was received. */
> +      uint32_t in_phy_port;   /* Physical Port on which frame was received. 
> */
> +      uint16_t total_len;     /* Full length of frame. */
> +      uint8_t reason;         /* Reason packet is being sent (one of OFPR_*) 
> */
> +      uint8_t table_id;       /* ID of the table that was looked up */
> +      uint8_t data[0];        /* Ethernet frame, halfway through 32-bit word,
> +                                 so the IP header is 32-bit aligned.  The
> +                                 amount of data is inferred from the length
> +                                 field in the header.  Because of padding,
> +                                 offsetof(struct ofp_packet_in, data) ==
> +                                 sizeof(struct ofp_packet_in) - 2. */
> +  };
> +  OFP_ASSERT(sizeof(struct ofp_packet_in) == 24);
> +
> +The confusing part is the comment on the data[] member.  This comment
> +is a leftover from OF1.0 openflow.h, in which the comment was correct:
> +sizeof(struct ofp_packet_in) is 20 in OF1.0 and offsetof(struct
> +ofp_packet_in, data) is 18.  When OF1.1 was written, the structure
> +members were changed but the comment was carelessly not updated, and
> +the comment became wrong: sizeof(struct ofp_packet_in) and
> +offsetof(struct ofp_packet_in, data) are both 24 in OF1.1.
> +
> +That leaves the question of how to implement ofp_packet_in in OF1.1.
> +The OpenFlow reference implementation for OF1.1 does not include any
> +padding, that is, the first byte of the encapsulated frame immediately
> +follows the 'table_id' member without a gap.  Open vSwitch therefore
> +implements it the same way for compatibility.

That seems entirely sensible.

> +
> +For an earlier discussion, please see the thread archived at:
> +https://mailman.stanford.edu/pipermail/openflow-discuss/2011-August/002604.html
> +
> +[*] The quoted definition is directly from OF1.1.  Definitions used
> +    inside OVS omit the 8-byte ofp_header members, so the sizes in
> +    this discussion are 8 bytes larger than those declared in OVS
> +    header files.
> +
> +
>  VLAN Matching
>  =============
>  
> diff --git a/include/openflow/openflow-1.1.h b/include/openflow/openflow-1.1.h
> index 4ee9c5c..004e61b 100644
> --- a/include/openflow/openflow-1.1.h
> +++ b/include/openflow/openflow-1.1.h
> @@ -753,12 +753,7 @@ struct ofp11_packet_in {
>      ovs_be16 total_len;     /* Full length of frame. */
>      uint8_t reason;         /* Reason packet is being sent (one of OFPR_*) */
>      uint8_t table_id;       /* ID of the table that was looked up */
> -    /* uint8_t data[0];        Ethernet frame, halfway through 32-bit word,
> -                               so the IP header is 32-bit aligned. The
> -                               amount of data is inferred from the length
> -                               field in the header. Because of padding,
> -                               offsetof(struct ofp_packet_in, data) ==
> -                               sizeof(struct ofp_packet_in) - 2. */
> +    /* Followed by Ethernet frame. */
>  };
>  OFP_ASSERT(sizeof(struct ofp11_packet_in) == 16);
>  
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index b4723b8..7fc4c7c 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -3196,6 +3196,23 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin,
>          pin->reason = opi->reason;
>          pin->buffer_id = ntohl(opi->buffer_id);
>          pin->total_len = ntohs(opi->total_len);
> +    } else if (raw == OFPRAW_OFPT11_PACKET_IN) {
> +        const struct ofp11_packet_in *opi;
> +        enum ofperr error;
> +
> +        opi = ofpbuf_pull(&b, sizeof *opi);
> +
> +        pin->packet = b.data;
> +        pin->packet_len = b.size;
> +
> +        pin->buffer_id = ntohl(opi->buffer_id);
> +        error = ofputil_port_from_ofp11(opi->in_port, &pin->fmd.in_port);
> +        if (error) {
> +            return error;
> +        }
> +        pin->total_len = ntohs(opi->total_len);
> +        pin->reason = opi->reason;
> +        pin->table_id = opi->table_id;
>      } else if (raw == OFPRAW_NXT_PACKET_IN) {
>          const struct nx_packet_in *npi;
>          struct match match;
> @@ -3310,6 +3327,27 @@ ofputil_encode_nx_packet_in(const struct 
> ofputil_packet_in *pin)
>  }
>  
>  static struct ofpbuf *
> +ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in *pin)
> +{
> +    struct ofp11_packet_in *opi;
> +    struct ofpbuf *packet;
> +
> +    packet = ofpraw_alloc_xid(OFPRAW_OFPT11_PACKET_IN, OFP11_VERSION,
> +                              htonl(0), pin->packet_len);
> +    opi = ofpbuf_put_zeros(packet, sizeof *opi);
> +    opi->buffer_id = htonl(pin->buffer_id);
> +    opi->in_port = ofputil_port_to_ofp11(pin->fmd.in_port);
> +    opi->in_phy_port = opi->in_port;
> +    opi->total_len = htons(pin->total_len);
> +    opi->reason = pin->reason;
> +    opi->table_id = pin->table_id;
> +
> +    ofpbuf_put(packet, pin->packet, pin->packet_len);
> +
> +    return packet;
> +}
> +
> +static struct ofpbuf *
>  ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin,
>                                 enum ofputil_protocol protocol)
>  {
> @@ -3373,7 +3411,8 @@ ofputil_encode_packet_in(const struct ofputil_packet_in 
> *pin,
>          break;
>  
>      case OFPUTIL_P_OF11_STD:
> -        NOT_REACHED();
> +        packet = ofputil_encode_ofp11_packet_in(pin);
> +        break;
>  
>      case OFPUTIL_P_OF12_OXM:
>      case OFPUTIL_P_OF13_OXM:
> diff --git a/tests/ofp-print.at b/tests/ofp-print.at
> index 82e8c3d..2f09c1b 100644
> --- a/tests/ofp-print.at
> +++ b/tests/ofp-print.at
> @@ -469,6 +469,21 @@ 
> tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:0
>  ])
>  AT_CLEANUP
>  
> +AT_SETUP([OFPT_PACKET_IN - OF1.1])
> +AT_KEYWORDS([ofp-print])
> +AT_CHECK([ovs-ofctl ofp-print "\
> +02 0a 00 54 00 00 00 00 00 00 01 11 00 00 00 03 \
> +00 00 00 03 00 3c 00 00 \
> +50 54 00 00 00 06 50 54 00 00 00 05 08 00 \
> +45 00 00 28 bd 12 00 00 40 06 3c 6a c0 a8 00 01 \
> +c0 a8 00 02 27 2f 00 00 78 50 cc 5b 57 af 42 1e \
> +50 02 02 00 26 e8 00 00 00 00 00 00 00 00 \
> +"], [0], [dnl
> +OFPT_PACKET_IN (OF1.1) (xid=0x0): total_len=60 in_port=3 (via no_match) 
> data_len=60 buffer=0x00000111
> +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=10031,tp_dst=0,tcp_flags=0x002
>  tcp_csum:26e8
> +])
> +AT_CLEANUP
> +
>  AT_SETUP([OFPT_PACKET_IN - OF1.2])
>  AT_KEYWORDS([ofp-print])
>  AT_CHECK([ovs-ofctl ofp-print "\
> diff --git a/tests/ofproto.at b/tests/ofproto.at
> index 27b6b34..be7387d 100644
> --- a/tests/ofproto.at
> +++ b/tests/ofproto.at
> @@ -1757,6 +1757,39 @@ OFPT_BARRIER_REPLY (OF1.2):
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
>  
> +dnl This test checks that OFPT_PACKET_OUT accepts both OFPP_NONE (as
> +dnl specified by OpenFlow 1.1) and OFPP_CONTROLLER (used by some
> +dnl controllers despite the spec) as meaning a packet that was generated
> +dnl by the controller.
> +AT_SETUP([ofproto - packet-out from controller (OpenFlow 1.1)])
> +OVS_VSWITCHD_START
> +
> +# Start a monitor listening for packet-ins.
> +AT_CHECK([ovs-ofctl -O OpenFlow11 monitor br0 --detach --no-chdir --pidfile])
> +ovs-appctl -t ovs-ofctl ofctl/send 0209000c0123456700000080
> +ovs-appctl -t ovs-ofctl ofctl/barrier
> +ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
> +AT_CAPTURE_FILE([monitor.log])
> +
> +# Send some packet-outs with OFPP_NONE and OFPP_CONTROLLER (65533) as 
> in_port.
> +AT_CHECK([ovs-ofctl -O OpenFlow11 packet-out br0 none controller 
> '0001020304050010203040501234'])
> +AT_CHECK([ovs-ofctl -O OpenFlow11 packet-out br0 4294967293 controller 
> '0001020304050010203040505678'])
> +
> +# Stop the monitor and check its output.
> +ovs-appctl -t ovs-ofctl ofctl/barrier
> +ovs-appctl -t ovs-ofctl exit
> +
> +AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl
> +OFPT_PACKET_IN (OF1.1): total_len=14 in_port=ANY (via action) data_len=14 
> (unbuffered)
> +metadata=0,in_port=0,vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x1234
> +OFPT_PACKET_IN (OF1.1): total_len=14 in_port=CONTROLLER (via action) 
> data_len=14 (unbuffered)
> +metadata=0,in_port=0,vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x5678
> +OFPT_BARRIER_REPLY (OF1.1):
> +])
> +
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
> +
>  dnl This test checks that metadata is encoded in packet_in structures,
>  dnl supported by NXAST.
>  AT_SETUP([ofproto - packet-out with metadata (NXM)])
> -- 
> 1.7.10.4
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
> 
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to