From OpenFlow Wiki
/* Copyright (c) 2008, 2009, 2010 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
* (Software) available for public use and benefit with the expectation
* that others will use, modify and enhance the Software and contribute
* those enhancements back to the community. However, since we would
* like to make the Software available for broadest use, with as few
* restrictions as possible permission is hereby granted, free of
* charge, to any person obtaining a copy of this Software to deal in
* the Software under the copyrights without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* The name and trademarks of copyright holder(s) may NOT be used in
* advertising or publicity pertaining to the Software or any
* derivatives without specific, written prior permission.
*/
#if !defined(OF_HW_API_H)
#define OF_HW_API_H
/*
* OpenFlow hardware API definition
*
* This header file provides an abstraction of the flow table and
* port operations that can be used to build a driver for hardware
* that implements the OpenFlow protocol.
*
* Currently this driver depends (extends) the sw_table defined
* in the udatapath/table.h file. Hopefully that file will be
* moved up to library status to support kernel and userspace
* implementations.
*
*/
#include <openflow/openflow.h>
#include <udatapath/table.h> /* For sw_table */
/* REQUIRES:
* struct sw_table defined
* TBD: We could remove this restriction; it's mainly so that
* current chain.c operations can work. It also allows
* pointer coersion between the two types.
*
* Eventually, sw_table may be extended to include everything in
* this driver.
*
* pointer to struct datapath
*/
/**************** basic types ****************/
typedef uint32_t of_port_t;
typedef struct of_hw_driver of_hw_driver_t;
/**************** packet ****************/
/* The OpenFlow hardware packet abstraction */
typedef void *os_pkt_t; /* OS representation of packet */
/* Requires monolithic packet data */
typedef struct of_packet_s {
unsigned char *data; /* Pointer to packet data */
int length; /* Length in bytes */
os_pkt_t os_pkt; /* OS specific representation */
} of_packet_t;
/* Init an of_packet struct from an ofp_buffer struct */
#define OF_PKT_INIT(pkt, ofp_buf) do { \
(pkt)->data = (ofp_buf)->data; \
(pkt)->length = (ofp_buf)->size; \
(pkt)->os_pkt = (ofp_buf); \
} while (0)
/**************** callback protos ****************/
/* packet in callback function prototype */
typedef int (*of_packet_in_f)(of_port_t port,
of_packet_t *packet,
int reason,
void *cookie);
typedef void (*of_port_change_f)(of_port_t port,
int state,
void *cookie);
/****************************************************************
*
* Hardware Driver
*
****************************************************************/
/* Hardware capabilities structure */
typedef struct of_hw_driver_caps {
/* Proposed Flags:
* COUNT_PKTS_OR_BYTES Can count either pkts or bytes, not both
* INTERNAL_PRI Support internal priority mapping, and thus
* normal enqueuing action
* LOCAL_CPU_THRU_TABLE Can send packets from the CPU through
* the flow table
*/
uint32_t flags;
/* Number of fully qualified flows supported (approx) */
int max_flows;
uint32_t wc_supported; /* Bitmap of OFPFW_* supported wildcards */
uint32_t actions_supported; /* Bitmap of OFPAT_* supported actions */
uint32_t ofpc_flags; /* Bitmap of ofp_capabilities flags */
} of_hw_driver_caps_t;
enum of_hw_driver_flags {
OF_HW_DRV_COUNT_PKTS_OR_BYTES = 1 << 0,
OF_HW_DRV_INTERNAL_PRI = 1 << 1,
OF_HW_DRV_CPU_PKTS_THRU_TABLE = 1 << 2
};
/**************** Constructor/Destructor ****************/
extern of_hw_driver_t *new_of_hw_driver(struct datapath *dp);
extern void delete_of_hw_driver(of_hw_driver_t *hw_drv);
/* TBD: Add a HW/DP init function? */
/**************** HW DataPath Driver Structure ****************/
/* Extends sw_table */
struct of_hw_driver {
/*
* Notes on sw_table inheritance:
*
* See above as well
*
* n_lookup and n_matched are not dynamically updated, but the
* call to table_stats_update should set them
*/
struct sw_table sw_table;
/* HW datapath capabilities structure */
of_hw_driver_caps_t caps;
/* OPTIONAL
* init(table, flags)
*
* Initialize necessary hardware and software to run
* the switching table. Must be called prior to any other calls
* into the table (except maybe some ioctls?).
*
* Proposed flags include:
* BYTES/PACKETS: If COUNT_PKTS_OR_BYTES, which to count by default
* REATTACH: Inidicates HW was running, don't re-initialize HW
*
*/
int (*init)(of_hw_driver_t *hw_drv, uint32_t flags);
/*
* table_stats_get(table, stats)
* port_stats_get(port, stats)
* flow_stats_get(flow_desc, stats)
* aggregate_stats_get(flow_desc, stats)
*
* Fill out the stats object(s) for this table/port/flow(s)/set of flows
*
* Returns 0 on success.
*
* For all but flow_stats, the routine fills out a pre-allocated
* stats structure. For flow stats, an array of stats is allocated
* by the called routine with *count elements. It must be freed by
* the caller.
*
* (Optional? If count is NULL for flow_stats_get, find a single
* match with exactly the given ofp_match.)
*/
int (*table_stats_get)(of_hw_driver_t *hw_drv, struct
ofp_table_stats *stats);
int (*port_stats_get)(of_hw_driver_t *hw_drv, int of_port,
struct ofp_port_stats *stats);
int (*flow_stats_get)(of_hw_driver_t *hw_drv, struct ofp_match,
struct ofp_flow_stats **stats, int *count);
int (*aggregate_stats_get)(struct ofp_match,
struct ofp_aggregate_stats_reply *stats);
/*
* port_add/remove(table, port)
*
* The indicated port has been added to/removed from the datapath
* Add also maps the of_port number to the hw_port indicated
*/
int (*port_add)(of_hw_driver_t *hw_drv, int of_port, const char *hw_name);
int (*port_remove)(of_hw_driver_t *hw_drv, of_port_t port);
/*
* port_link_get(table, port)
* port_enable_set(table, port, enable)
* port_enable_get(table, port)
*
* Get/set the indicated properties of a port. Only real ports
* set with port_add are supported.
*/
int (*port_link_get)(of_hw_driver_t *hw_drv, int of_port);
int (*port_enable_set)(of_hw_driver_t *hw_drv, int of_port, int enable);
int (*port_enable_get)(of_hw_driver_t *hw_drv, int of_port);
/*
* port_queue_config(drv, port, qid, min-bw)
* port_queue_remove(drv, port, qid)
*
* Port queue control. Config will add the queue if not present
*/
int (*port_queue_config)(of_hw_driver_t *hw_drv, int of_port,
uint32_t qid, int min_bw);
int (*port_queue_remove)(of_hw_driver_t *hw_drv, int of_port,
uint32_t qid);
/*
* port_change_register
*
* Register a callback function to receive port change notifications
* from ports in this datapath
*/
int (*port_change_register)(of_hw_driver_t *hw_drv,
of_port_change_f callback, void *cookie);
/*
* packet_send(table, of_port, pkt, flags)
*
* Send packet to an openflow port.
*
* Proposed flags:
* APPLY_FLOW_TABLE: If set, and if the hardware supports
* it, send the packet through the flow table with the source
* port being the local CPU port. (Would be nice to have
* a flexible source port indicated; could hide in flags...)
*
* TBD: Owner of pkt and pkt->data after call; sync/async.
*/
int (*packet_send)(of_hw_driver_t *hw_drv, int of_port, of_packet_t *pkt,
uint32_t flags);
/*
* packet_receive_register
*
* Register a callback function to receive packets from ports in
* this datapath
*
* TBD: Semantics for owning packets and return codes so indicating.
*/
int (*packet_receive_register)(of_hw_driver_t *hw_drv,
of_packet_in_f callback, void *cookie);
/* OPTIONAL
* ioctl(table, request, io_param)
*
* Execute an ioctl on the table. A few ioctls are predefined,
* but most will be implementation specific.
* Returns 0 on success or an implementation specific other code.
*
* io_param is an input/output parameter whose value may be
* returned to the caller.
* io_len is the length of io_param in bytes.
* On input, the *io_param pointer may clobbered, so the caller must
* maintain it for deallocation if necessary.
* On output, when used -- which depends on the operation --
* the *io_param is a pointer to a buffer allocated by the ioctl
* routine, but owned by the calling routine.
*
* Question: Should a full I/O buffer be supported?
* ioctl(table, op, in_buf, in_len, out_buf, out_len); or
* ioctl(table, op, io_buf, io_len); where buf/len set on output.
*
* Proposed operations:
* Set debug level
* Clear port/flow/table stats
* Select packet or byte counter collection
*/
int (*ioctl)(of_hw_driver_t *hw_drv, uint32_t op, void **io_param,
int *io_len);
};
/**************** IOCTL values ****************/
enum of_hw_ioctl_e {
OF_HW_IOCTL_TABLE_DEBUG_SET = 1,
OF_HW_IOCTL_PORT_DEBUG_SET = 2,
OF_HW_IOCTL_BYTE_PKT_CNTR_SET = 3
};
/* Values for OF_HW_IOCTL_BYTE_PKT_CNTR_SET */
#define OF_HW_CNTR_PACKETS 0
#define OF_HW_CNTR_BYTES 1
enum of_hw_error_e {
OF_HW_OKAY = 0,
OF_HW_ERROR = -1,
OF_HW_PORT_DOWN = -2
};
#endif /* OF_HW_API_H */