Rewrite IP ToS/DSCP: Add IP ToS/DSCP field rewrite feature
This commit is contained in:
@@ -195,6 +195,34 @@ set_nw_addr(struct sk_buff *skb, struct sw_flow_key *key,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
set_nw_tos(struct sk_buff *skb, struct sw_flow_key *key,
|
||||
const struct ofp_action_header *ah)
|
||||
{
|
||||
struct ofp_action_nw_tos *nt = (struct ofp_action_nw_tos *)ah;
|
||||
uint16_t eth_proto = ntohs(key->dl_type);
|
||||
|
||||
if (eth_proto == ETH_P_IP) {
|
||||
struct iphdr *nh = ip_hdr(skb);
|
||||
uint8_t new, *field;
|
||||
|
||||
/* JeanII : Set only 6 bits, don't clobber ECN */
|
||||
new = (nt->nw_tos & 0xFC) | (nh->tos & 0x03);
|
||||
|
||||
/* Get address of field */
|
||||
field = &nh->tos;
|
||||
/* jklee : ip tos field is not included in TCP pseudo header.
|
||||
* Need magic as update_csum() don't work with 8 bits. */
|
||||
update_csum(&nh->check, skb, htons((uint16_t)*field),
|
||||
htons((uint16_t)new), 0);
|
||||
|
||||
/* Update in packet */
|
||||
*field = new;
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
set_tp_port(struct sk_buff *skb, struct sw_flow_key *key,
|
||||
const struct ofp_action_header *ah)
|
||||
@@ -293,6 +321,12 @@ static const struct openflow_action of_actions[] = {
|
||||
NULL,
|
||||
set_nw_addr
|
||||
},
|
||||
[OFPAT_SET_NW_TOS] = {
|
||||
sizeof(struct ofp_action_nw_tos),
|
||||
sizeof(struct ofp_action_nw_tos),
|
||||
NULL,
|
||||
set_nw_tos
|
||||
},
|
||||
[OFPAT_SET_TP_SRC] = {
|
||||
sizeof(struct ofp_action_tp_port),
|
||||
sizeof(struct ofp_action_tp_port),
|
||||
|
||||
+56
-56
@@ -1,6 +1,6 @@
|
||||
/* Copyright (c) 2008 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
|
||||
@@ -13,10 +13,10 @@
|
||||
* 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
|
||||
@@ -25,7 +25,7 @@
|
||||
* 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.
|
||||
@@ -61,7 +61,7 @@
|
||||
#endif
|
||||
|
||||
/* The most significant bit being set in the version field indicates an
|
||||
* experimental OpenFlow version.
|
||||
* experimental OpenFlow version.
|
||||
*/
|
||||
#define OFP_VERSION 0x97
|
||||
|
||||
@@ -79,18 +79,18 @@ enum ofp_port {
|
||||
OFPP_MAX = 0xff00,
|
||||
|
||||
/* Fake output "ports". */
|
||||
OFPP_IN_PORT = 0xfff8, /* Send the packet out the input port. This
|
||||
virtual port must be explicitly used
|
||||
in order to send back out of the input
|
||||
OFPP_IN_PORT = 0xfff8, /* Send the packet out the input port. This
|
||||
virtual port must be explicitly used
|
||||
in order to send back out of the input
|
||||
port. */
|
||||
OFPP_TABLE = 0xfff9, /* Perform actions in flow table.
|
||||
OFPP_TABLE = 0xfff9, /* Perform actions in flow table.
|
||||
NB: This can only be the destination
|
||||
port for packet-out messages. */
|
||||
OFPP_NORMAL = 0xfffa, /* Process with normal L2/L3 switching. */
|
||||
OFPP_FLOOD = 0xfffb, /* All physical ports except input port and
|
||||
OFPP_FLOOD = 0xfffb, /* All physical ports except input port and
|
||||
those disabled by STP. */
|
||||
OFPP_ALL = 0xfffc, /* All physical ports except input port. */
|
||||
OFPP_CONTROLLER = 0xfffd, /* Send to controller. */
|
||||
OFPP_CONTROLLER = 0xfffd, /* Send to controller. */
|
||||
OFPP_LOCAL = 0xfffe, /* Local openflow "port". */
|
||||
OFPP_NONE = 0xffff /* Not associated with a physical port. */
|
||||
};
|
||||
@@ -178,7 +178,7 @@ enum ofp_capabilities {
|
||||
|
||||
/* Flags to indicate behavior of the physical port. These flags are
|
||||
* used in ofp_phy_port to describe the current configuration. They are
|
||||
* used in the ofp_port_mod message to configure the port's behavior.
|
||||
* used in the ofp_port_mod message to configure the port's behavior.
|
||||
*/
|
||||
enum ofp_port_config {
|
||||
OFPPC_PORT_DOWN = 1 << 0, /* Port is administratively down. */
|
||||
@@ -286,15 +286,15 @@ struct ofp_port_mod {
|
||||
struct ofp_header header;
|
||||
uint16_t port_no;
|
||||
uint8_t hw_addr[OFP_ETH_ALEN]; /* The hardware address is not
|
||||
configurable. This is used to
|
||||
sanity-check the request, so it must
|
||||
configurable. This is used to
|
||||
sanity-check the request, so it must
|
||||
be the same as returned in an
|
||||
ofp_phy_port struct. */
|
||||
|
||||
uint32_t config; /* Bitmap of OFPPC_* flags. */
|
||||
uint32_t mask; /* Bitmap of OFPPC_* flags to be changed. */
|
||||
|
||||
uint32_t advertise; /* Bitmap of "ofp_port_features"s. Zero all
|
||||
uint32_t advertise; /* Bitmap of "ofp_port_features"s. Zero all
|
||||
bits to prevent any action taking place. */
|
||||
uint8_t pad[4]; /* Pad to 64-bits. */
|
||||
};
|
||||
@@ -315,7 +315,7 @@ struct ofp_packet_in {
|
||||
uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */
|
||||
uint8_t pad;
|
||||
uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word,
|
||||
so the IP header is 32-bit aligned. The
|
||||
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) ==
|
||||
@@ -338,9 +338,9 @@ enum ofp_action_type {
|
||||
OFPAT_VENDOR = 0xffff
|
||||
};
|
||||
|
||||
/* Action structure for OFPAT_OUTPUT, which sends packets out 'port'.
|
||||
* When the 'port' is the OFPP_CONTROLLER, 'max_len' indicates the max
|
||||
* number of bytes to send. A 'max_len' of zero means the entire packet
|
||||
/* Action structure for OFPAT_OUTPUT, which sends packets out 'port'.
|
||||
* When the 'port' is the OFPP_CONTROLLER, 'max_len' indicates the max
|
||||
* number of bytes to send. A 'max_len' of zero means the entire packet
|
||||
* should be sent. */
|
||||
struct ofp_action_output {
|
||||
uint16_t type; /* OFPAT_OUTPUT. */
|
||||
@@ -406,25 +406,25 @@ struct ofp_action_nw_tos {
|
||||
uint8_t nw_tos; /* IP ToS/DSCP (6 bits). */
|
||||
uint8_t pad[3];
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_action_nw_addr) == 8);
|
||||
OFP_ASSERT(sizeof(struct ofp_action_nw_tos) == 8);
|
||||
|
||||
/* Action header for OFPAT_VENDOR. The rest of the body is vendor-defined. */
|
||||
struct ofp_action_vendor_header {
|
||||
uint16_t type; /* OFPAT_VENDOR. */
|
||||
uint16_t len; /* Length is 8. */
|
||||
uint32_t vendor; /* Vendor ID, which takes the same form
|
||||
as in "struct ofp_vendor_header". */
|
||||
uint32_t vendor; /* Vendor ID, which takes the same form
|
||||
as in "struct ofp_vendor_header". */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_action_vendor_header) == 8);
|
||||
|
||||
/* Action header that is common to all actions. The length includes the
|
||||
* header and any padding used to make the action 64-bit aligned.
|
||||
* header and any padding used to make the action 64-bit aligned.
|
||||
* NB: The length of an action *must* always be a multiple of eight. */
|
||||
struct ofp_action_header {
|
||||
uint16_t type; /* One of OFPAT_*. */
|
||||
uint16_t len; /* Length of action, including this
|
||||
header. This is the length of action,
|
||||
including any padding to make it
|
||||
uint16_t len; /* Length of action, including this
|
||||
header. This is the length of action,
|
||||
including any padding to make it
|
||||
64-bit aligned. */
|
||||
uint8_t pad[4];
|
||||
};
|
||||
@@ -437,8 +437,8 @@ struct ofp_packet_out {
|
||||
uint16_t in_port; /* Packet's input port (OFPP_NONE if none). */
|
||||
uint16_t actions_len; /* Size of action array in bytes. */
|
||||
struct ofp_action_header actions[0]; /* Actions. */
|
||||
/* uint8_t data[0]; */ /* Packet data. The length is inferred
|
||||
from the length field in the header.
|
||||
/* uint8_t data[0]; */ /* Packet data. The length is inferred
|
||||
from the length field in the header.
|
||||
(Only meaningful if buffer_id == -1.) */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_packet_out) == 16);
|
||||
@@ -483,7 +483,7 @@ enum ofp_flow_wildcards {
|
||||
OFPFW_ALL = ((1 << 21) - 1)
|
||||
};
|
||||
|
||||
/* The wildcards for ICMP type and code fields use the transport source
|
||||
/* The wildcards for ICMP type and code fields use the transport source
|
||||
* and destination port fields, respectively. */
|
||||
#define OFPFW_ICMP_TYPE OFPFW_TP_SRC
|
||||
#define OFPFW_ICMP_CODE OFPFW_TP_DST
|
||||
@@ -521,7 +521,7 @@ struct ofp_match {
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_match) == 36);
|
||||
|
||||
/* The match fields for ICMP type and code use the transport source and
|
||||
/* The match fields for ICMP type and code use the transport source and
|
||||
* destination port fields, respectively. */
|
||||
#define icmp_type tp_src
|
||||
#define icmp_code tp_dst
|
||||
@@ -549,16 +549,16 @@ struct ofp_flow_mod {
|
||||
uint16_t idle_timeout; /* Idle time before discarding (seconds). */
|
||||
uint16_t hard_timeout; /* Max time before discarding (seconds). */
|
||||
uint16_t priority; /* Priority level of flow entry. */
|
||||
uint32_t buffer_id; /* Buffered packet to apply to (or -1).
|
||||
uint32_t buffer_id; /* Buffered packet to apply to (or -1).
|
||||
Not meaningful for OFPFC_DELETE*. */
|
||||
uint16_t out_port; /* For OFPFC_DELETE* commands, require
|
||||
matching entries to include this as an
|
||||
output port. A value of OFPP_NONE
|
||||
matching entries to include this as an
|
||||
output port. A value of OFPP_NONE
|
||||
indicates no restriction. */
|
||||
uint16_t flags; /* One of OFPFF_*. */
|
||||
uint32_t reserved; /* Reserved for future use. */
|
||||
struct ofp_action_header actions[0]; /* The action length is inferred
|
||||
from the length field in the
|
||||
struct ofp_action_header actions[0]; /* The action length is inferred
|
||||
from the length field in the
|
||||
header. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_flow_mod) == 64);
|
||||
@@ -582,7 +582,7 @@ struct ofp_flow_expired {
|
||||
uint32_t duration; /* Time flow was alive in seconds. */
|
||||
uint16_t idle_timeout; /* Idle timeout from original flow mod. */
|
||||
uint8_t pad2[2]; /* Align to 64-bits. */
|
||||
uint64_t packet_count;
|
||||
uint64_t packet_count;
|
||||
uint64_t byte_count;
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_flow_expired) == 72);
|
||||
@@ -610,13 +610,13 @@ enum ofp_bad_request_code {
|
||||
OFPBRC_BAD_VERSION, /* ofp_header.version not supported. */
|
||||
OFPBRC_BAD_TYPE, /* ofp_header.type not supported. */
|
||||
OFPBRC_BAD_STAT, /* ofp_stats_request.type not supported. */
|
||||
OFPBRC_BAD_VENDOR, /* Vendor not supported (in ofp_vendor_header
|
||||
OFPBRC_BAD_VENDOR, /* Vendor not supported (in ofp_vendor_header
|
||||
* or ofp_stats_request or ofp_stats_reply). */
|
||||
OFPBRC_BAD_SUBTYPE, /* Vendor subtype not supported. */
|
||||
OFPBRC_EPERM /* Permissions error. */
|
||||
};
|
||||
|
||||
/* ofp_error_msg 'code' values for OFPET_BAD_ACTION. 'data' contains at least
|
||||
/* ofp_error_msg 'code' values for OFPET_BAD_ACTION. 'data' contains at least
|
||||
* the first 64 bytes of the failed request. */
|
||||
enum ofp_bad_action_code {
|
||||
OFPBAC_BAD_TYPE, /* Unknown action type. */
|
||||
@@ -628,11 +628,11 @@ enum ofp_bad_action_code {
|
||||
OFPBAC_EPERM /* Permissions error. */
|
||||
};
|
||||
|
||||
/* ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED. 'data' contains
|
||||
/* ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED. 'data' contains
|
||||
* at least the first 64 bytes of the failed request. */
|
||||
enum ofp_flow_mod_failed_code {
|
||||
OFPFMFC_ALL_TABLES_FULL, /* Flow not added because of full tables. */
|
||||
OFPFMFC_OVERLAP, /* Attempted to add overlapping flow with
|
||||
OFPFMFC_OVERLAP, /* Attempted to add overlapping flow with
|
||||
* CHECK_OVERLAP flag set. */
|
||||
OFPFMFC_EPERM /* Permissions error. */
|
||||
};
|
||||
@@ -643,13 +643,13 @@ struct ofp_error_msg {
|
||||
|
||||
uint16_t type;
|
||||
uint16_t code;
|
||||
uint8_t data[0]; /* Variable-length data. Interpreted based
|
||||
uint8_t data[0]; /* Variable-length data. Interpreted based
|
||||
on the type and code. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_error_msg) == 12);
|
||||
|
||||
enum ofp_stats_types {
|
||||
/* Description of this OpenFlow switch.
|
||||
/* Description of this OpenFlow switch.
|
||||
* The request body is empty.
|
||||
* The reply body is struct ofp_desc_stats. */
|
||||
OFPST_DESC,
|
||||
@@ -676,7 +676,7 @@ enum ofp_stats_types {
|
||||
|
||||
/* Vendor extension.
|
||||
* The request and reply bodies begin with a 32-bit vendor ID, which takes
|
||||
* the same form as in "struct ofp_vendor_header". The request and reply
|
||||
* the same form as in "struct ofp_vendor_header". The request and reply
|
||||
* bodies are otherwise vendor-defined. */
|
||||
OFPST_VENDOR = 0xffff
|
||||
};
|
||||
@@ -703,7 +703,7 @@ OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
|
||||
|
||||
#define DESC_STR_LEN 256
|
||||
#define SERIAL_NUM_LEN 32
|
||||
/* Body of reply to OFPST_DESC request. Each entry is a NULL-terminated
|
||||
/* Body of reply to OFPST_DESC request. Each entry is a NULL-terminated
|
||||
* ASCII string. */
|
||||
struct ofp_desc_stats {
|
||||
char mfr_desc[DESC_STR_LEN]; /* Manufacturer description. */
|
||||
@@ -719,8 +719,8 @@ struct ofp_flow_stats_request {
|
||||
uint8_t table_id; /* ID of table to read (from ofp_table_stats),
|
||||
0xff for all tables or 0xfe for emergency. */
|
||||
uint8_t pad; /* Align to 32 bits. */
|
||||
uint16_t out_port; /* Require matching entries to include this
|
||||
as an output port. A value of OFPP_NONE
|
||||
uint16_t out_port; /* Require matching entries to include this
|
||||
as an output port. A value of OFPP_NONE
|
||||
indicates no restriction. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 40);
|
||||
@@ -749,8 +749,8 @@ struct ofp_aggregate_stats_request {
|
||||
uint8_t table_id; /* ID of table to read (from ofp_table_stats)
|
||||
0xff for all tables or 0xfe for emergency. */
|
||||
uint8_t pad; /* Align to 32 bits. */
|
||||
uint16_t out_port; /* Require matching entries to include this
|
||||
as an output port. A value of OFPP_NONE
|
||||
uint16_t out_port; /* Require matching entries to include this
|
||||
as an output port. A value of OFPP_NONE
|
||||
indicates no restriction. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_aggregate_stats_request) == 40);
|
||||
@@ -770,7 +770,7 @@ struct ofp_table_stats {
|
||||
are consulted first. */
|
||||
uint8_t pad[3]; /* Align to 32-bits. */
|
||||
char name[OFP_MAX_TABLE_NAME_LEN];
|
||||
uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are
|
||||
uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are
|
||||
supported by the table. */
|
||||
uint32_t max_entries; /* Max number of entries supported. */
|
||||
uint32_t active_count; /* Number of active entries. */
|
||||
@@ -788,20 +788,20 @@ struct ofp_port_stats {
|
||||
uint64_t tx_packets; /* Number of transmitted packets. */
|
||||
uint64_t rx_bytes; /* Number of received bytes. */
|
||||
uint64_t tx_bytes; /* Number of transmitted bytes. */
|
||||
uint64_t rx_dropped; /* Number of packets dropped by RX. */
|
||||
uint64_t tx_dropped; /* Number of packets dropped by TX. */
|
||||
uint64_t rx_dropped; /* Number of packets dropped by RX. */
|
||||
uint64_t tx_dropped; /* Number of packets dropped by TX. */
|
||||
uint64_t rx_errors; /* Number of receive errors. This is a super-set
|
||||
of more specific receive errors and should be
|
||||
greater than or equal to the sum of all
|
||||
greater than or equal to the sum of all
|
||||
rx_*_err values. */
|
||||
uint64_t tx_errors; /* Number of transmit errors. This is a super-set
|
||||
of more specific transmit errors and should be
|
||||
greater than or equal to the sum of all
|
||||
tx_*_err values (none currently defined.) */
|
||||
uint64_t rx_frame_err; /* Number of frame alignment errors. */
|
||||
uint64_t rx_over_err; /* Number of packets with RX overrun. */
|
||||
uint64_t rx_crc_err; /* Number of CRC errors. */
|
||||
uint64_t collisions; /* Number of collisions. */
|
||||
uint64_t rx_frame_err; /* Number of frame alignment errors. */
|
||||
uint64_t rx_over_err; /* Number of packets with RX overrun. */
|
||||
uint64_t rx_crc_err; /* Number of CRC errors. */
|
||||
uint64_t collisions; /* Number of collisions. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct ofp_port_stats) == 104);
|
||||
|
||||
|
||||
@@ -263,6 +263,10 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
|
||||
sizeof(struct ofp_action_nw_addr),
|
||||
sizeof(struct ofp_action_nw_addr),
|
||||
},
|
||||
[OFPAT_SET_NW_TOS] = {
|
||||
sizeof(struct ofp_action_nw_tos),
|
||||
sizeof(struct ofp_action_nw_tos),
|
||||
},
|
||||
[OFPAT_SET_TP_SRC] = {
|
||||
sizeof(struct ofp_action_tp_port),
|
||||
sizeof(struct ofp_action_tp_port),
|
||||
@@ -363,6 +367,12 @@ ofp_print_action(struct ds *string, const struct ofp_action_header *ah,
|
||||
break;
|
||||
}
|
||||
|
||||
case OFPAT_SET_NW_TOS: {
|
||||
struct ofp_action_nw_tos *nt = (struct ofp_action_nw_tos *)ah;
|
||||
ds_put_format(string, "mod_ip_tos:%d", nt->nw_tos);
|
||||
break;
|
||||
}
|
||||
|
||||
case OFPAT_SET_TP_SRC: {
|
||||
struct ofp_action_tp_port *ta = (struct ofp_action_tp_port *)ah;
|
||||
ds_put_format(string, "mod_tp_src:%d", ntohs(ta->tp_port));
|
||||
|
||||
+163
-159
@@ -271,20 +271,19 @@ sub setup_NF2 {
|
||||
|
||||
|
||||
sub setup_user {
|
||||
setup_pcap_interfaces();
|
||||
|
||||
setup_pcap_interfaces();
|
||||
# create openflow switch on four ports
|
||||
my $if_string = '';
|
||||
for (my $i = 5 ; $i <= 7 ; $i++) {
|
||||
$if_string .= nftest_get_iface("eth$i") . ',';
|
||||
}
|
||||
$if_string .= nftest_get_iface("eth8");
|
||||
|
||||
# create openflow switch on four ports
|
||||
my $if_string = '';
|
||||
for ( my $i = 5 ; $i <= 7 ; $i++ ) {
|
||||
$if_string .= nftest_get_iface("eth$i") . ',';
|
||||
}
|
||||
$if_string .= nftest_get_iface("eth8");
|
||||
print "about to create ofdatapath` punix:/var/run/test -i $if_string \& \n";
|
||||
system("${openflow_dir}/udatapath/ofdatapath punix:/var/run/test -i $if_string \&");
|
||||
|
||||
print "about to create ofdatapath` punix:/var/run/test -i $if_string \& \n";
|
||||
system("${openflow_dir}/udatapath/ofdatapath punix:/var/run/test -i $if_string \&");
|
||||
|
||||
start_ofprotocol("unix:/var/run/test", @_);
|
||||
start_ofprotocol("unix:/var/run/test", @_);
|
||||
}
|
||||
|
||||
sub teardown_kmod {
|
||||
@@ -815,168 +814,173 @@ sub create_flow_mod_from_udp {
|
||||
}
|
||||
|
||||
sub flow_mod_length {
|
||||
my ( $mod_type, $chg_field ) = @_;
|
||||
my ($mod_type, $chg_field) = @_;
|
||||
|
||||
my $action_length;
|
||||
if ($mod_type eq 'drop') {
|
||||
$action_length = 0;
|
||||
} elsif (defined $chg_field) {
|
||||
if (($chg_field eq 'dl_src') || ($chg_field eq 'dl_dst')) {
|
||||
$action_length = $ofp->sizeof('ofp_action_dl_addr') +
|
||||
$ofp->sizeof('ofp_action_output');
|
||||
} elsif (($chg_field eq 'nw_src') || ($chg_field eq 'nw_dst')) {
|
||||
$action_length = $ofp->sizeof('ofp_action_nw_addr') +
|
||||
$ofp->sizeof('ofp_action_output');
|
||||
} elsif (($chg_field eq 'tp_src') || ($chg_field eq 'tp_dst')) {
|
||||
$action_length = $ofp->sizeof('ofp_action_tp_port') +
|
||||
$ofp->sizeof('ofp_action_output');
|
||||
} elsif ($chg_field eq 'strip_vlan') {
|
||||
$action_length = $ofp->sizeof('ofp_action_header') +
|
||||
$ofp->sizeof('ofp_action_output');
|
||||
} elsif ($chg_field eq 'vlan_vid') {
|
||||
$action_length = $ofp->sizeof('ofp_action_vlan_vid') +
|
||||
$ofp->sizeof('ofp_action_output');
|
||||
} elsif ($chg_field eq 'vlan_pcp') {
|
||||
$action_length = $ofp->sizeof('ofp_action_vlan_pcp') +
|
||||
$ofp->sizeof('ofp_action_output');
|
||||
} else {
|
||||
$action_length = $ofp->sizeof('ofp_action_output');
|
||||
}
|
||||
my $action_length = 0;
|
||||
|
||||
if ($mod_type eq 'drop') {
|
||||
$action_length = 0;
|
||||
} elsif (defined $chg_field) {
|
||||
if (($chg_field eq 'dl_src') || ($chg_field eq 'dl_dst')) {
|
||||
$action_length = $ofp->sizeof('ofp_action_dl_addr')
|
||||
+ $ofp->sizeof('ofp_action_output');
|
||||
} elsif (($chg_field eq 'nw_src') || ($chg_field eq 'nw_dst')) {
|
||||
$action_length = $ofp->sizeof('ofp_action_nw_addr')
|
||||
+ $ofp->sizeof('ofp_action_output');
|
||||
} elsif ($chg_field eq 'nw_tos') {
|
||||
$action_length = $ofp->sizeof('ofp_action_nw_tos')
|
||||
+ $ofp->sizeof('ofp_action_output');
|
||||
} elsif (($chg_field eq 'tp_src') || ($chg_field eq 'tp_dst')) {
|
||||
$action_length = $ofp->sizeof('ofp_action_tp_port')
|
||||
+ $ofp->sizeof('ofp_action_output');
|
||||
} elsif ($chg_field eq 'strip_vlan') {
|
||||
$action_length = $ofp->sizeof('ofp_action_header')
|
||||
+ $ofp->sizeof('ofp_action_output');
|
||||
} elsif ($chg_field eq 'vlan_vid') {
|
||||
$action_length = $ofp->sizeof('ofp_action_vlan_vid')
|
||||
+ $ofp->sizeof('ofp_action_output');
|
||||
} elsif ($chg_field eq 'vlan_pcp') {
|
||||
$action_length = $ofp->sizeof('ofp_action_vlan_pcp')
|
||||
+ $ofp->sizeof('ofp_action_output');
|
||||
} else {
|
||||
$action_length = $ofp->sizeof('ofp_action_output');
|
||||
$action_length = $ofp->sizeof('ofp_action_output');
|
||||
}
|
||||
my $length = $ofp->sizeof('ofp_flow_mod') + $action_length;
|
||||
return $length;
|
||||
} else {
|
||||
$action_length = $ofp->sizeof('ofp_action_output');
|
||||
}
|
||||
|
||||
my $length = $ofp->sizeof('ofp_flow_mod') + $action_length;
|
||||
return $length;
|
||||
}
|
||||
|
||||
sub combine_args {
|
||||
my ($flow_mod, $mod_type, $out_port, $chg_field, $chg_val) = @_;
|
||||
my ($flow_mod, $mod_type, $out_port, $chg_field, $chg_val) = @_;
|
||||
|
||||
my @pad_6 = (0,0,0,0,0,0);
|
||||
my @pad_4 = (0,0,0,0);
|
||||
my @pad_3 = (0,0,0);
|
||||
my @pad_2 = (0,0);
|
||||
my @pad_6 = (0,0,0,0,0,0);
|
||||
my @pad_4 = (0,0,0,0);
|
||||
my @pad_3 = (0,0,0);
|
||||
my @pad_2 = (0,0);
|
||||
|
||||
my $nw_addr_org;
|
||||
my $ok_org;
|
||||
my $nw_addr_org;
|
||||
my $ok_org;
|
||||
|
||||
my @dl_addr_org;
|
||||
my $chg_vlan_pcp_val;
|
||||
my @dl_addr_org;
|
||||
my $chg_vlan_pcp_val;
|
||||
|
||||
#OUTPUT
|
||||
#and No action for drops
|
||||
my $action_output_args;
|
||||
my $action_output;
|
||||
if ($mod_type ne 'drop') {
|
||||
$action_output_args = {
|
||||
type => $enums{'OFPAT_OUTPUT'},
|
||||
len => $ofp->sizeof('ofp_action_output'),
|
||||
port => $out_port,
|
||||
max_len => 0, # send entire packet
|
||||
};
|
||||
$action_output = $ofp->pack( 'ofp_action_output', $action_output_args );
|
||||
}
|
||||
#OUTPUT
|
||||
#and No action for drops
|
||||
my $action_output_args;
|
||||
my $action_output;
|
||||
if ($mod_type ne 'drop') {
|
||||
$action_output_args = {
|
||||
type => $enums{'OFPAT_OUTPUT'},
|
||||
len => $ofp->sizeof('ofp_action_output'),
|
||||
port => $out_port,
|
||||
max_len => 0, # send entire packet
|
||||
};
|
||||
$action_output = $ofp->pack('ofp_action_output', $action_output_args);
|
||||
}
|
||||
|
||||
#MODIFY ACTION
|
||||
my $action_mod_args;
|
||||
my $action_mod;
|
||||
if (defined $chg_field) {
|
||||
#SET_DL_SRC
|
||||
if ($chg_field eq 'dl_src') {
|
||||
@dl_addr_org = NF2::PDU::get_MAC_address($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_DL_SRC'},
|
||||
len => $ofp->sizeof('ofp_action_dl_addr'),
|
||||
dl_addr => \@dl_addr_org,
|
||||
pad => \@pad_6,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_dl_addr', $action_mod_args);
|
||||
#SET_DL_DST
|
||||
} elsif ($chg_field eq 'dl_dst') {
|
||||
@dl_addr_org = NF2::PDU::get_MAC_address($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_DL_DST'},
|
||||
len => $ofp->sizeof('ofp_action_dl_addr'),
|
||||
dl_addr => \@dl_addr_org,
|
||||
pad => \@pad_6,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_dl_addr', $action_mod_args);
|
||||
#SET_NW_SRC
|
||||
} elsif ($chg_field eq 'nw_src') {
|
||||
($nw_addr_org, $ok_org) = NF2::IP_hdr::getIP($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_NW_SRC'},
|
||||
len => $ofp->sizeof('ofp_action_nw_addr'),
|
||||
nw_addr => $nw_addr_org,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_nw_addr', $action_mod_args);
|
||||
#SET_NW_DST
|
||||
} elsif ($chg_field eq 'nw_dst') {
|
||||
($nw_addr_org, $ok_org) = NF2::IP_hdr::getIP($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_NW_DST'},
|
||||
len => $ofp->sizeof('ofp_action_nw_addr'),
|
||||
nw_addr => $nw_addr_org,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_nw_addr', $action_mod_args);
|
||||
#SET_TP_SRC
|
||||
} elsif ($chg_field eq 'tp_src') {
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_TP_SRC'},
|
||||
len => $ofp->sizeof('ofp_action_tp_port'),
|
||||
tp_port => $chg_val,
|
||||
pad => \@pad_2,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_tp_port', $action_mod_args);
|
||||
#SET_TP_DST
|
||||
} elsif ($chg_field eq 'tp_dst') {
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_TP_DST'},
|
||||
len => $ofp->sizeof('ofp_action_tp_port'),
|
||||
tp_port => $chg_val,
|
||||
pad => \@pad_2,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_tp_port', $action_mod_args);
|
||||
#STRIP_VLAN
|
||||
} elsif ($chg_field eq 'strip_vlan') {
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_STRIP_VLAN'},
|
||||
len => $ofp->sizeof('ofp_action_header'),
|
||||
pad => \@pad_4,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_header', $action_mod_args);
|
||||
#SET_VLAN_VID
|
||||
} elsif ($chg_field eq 'vlan_vid') {
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_VLAN_VID'},
|
||||
len => $ofp->sizeof('ofp_action_vlan_vid'),
|
||||
vlan_vid => $chg_val,
|
||||
pad => \@pad_2,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_vlan_vid', $action_mod_args);
|
||||
#SET_VLAN_PCP
|
||||
} elsif ($chg_field eq 'vlan_pcp') {
|
||||
$chg_vlan_pcp_val = ($chg_val>>13) & 0x0007;
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_VLAN_PCP'},
|
||||
len => $ofp->sizeof('ofp_action_vlan_pcp'),
|
||||
vlan_pcp => $chg_vlan_pcp_val,
|
||||
pad => \@pad_3,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_vlan_pcp', $action_mod_args);
|
||||
} else {
|
||||
$action_mod = undef;
|
||||
}
|
||||
#MODIFY ACTION
|
||||
my $action_mod_args;
|
||||
my $action_mod;
|
||||
if (defined $chg_field) {
|
||||
if ($chg_field eq 'dl_src') { #SET_DL_SRC
|
||||
@dl_addr_org = NF2::PDU::get_MAC_address($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_DL_SRC'},
|
||||
len => $ofp->sizeof('ofp_action_dl_addr'),
|
||||
dl_addr => \@dl_addr_org,
|
||||
pad => \@pad_6,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_dl_addr', $action_mod_args);
|
||||
} elsif ($chg_field eq 'dl_dst') { #SET_DL_DST
|
||||
@dl_addr_org = NF2::PDU::get_MAC_address($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_DL_DST'},
|
||||
len => $ofp->sizeof('ofp_action_dl_addr'),
|
||||
dl_addr => \@dl_addr_org,
|
||||
pad => \@pad_6,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_dl_addr', $action_mod_args);
|
||||
} elsif ($chg_field eq 'nw_src') { #SET_NW_SRC
|
||||
($nw_addr_org, $ok_org) = NF2::IP_hdr::getIP($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_NW_SRC'},
|
||||
len => $ofp->sizeof('ofp_action_nw_addr'),
|
||||
nw_addr => $nw_addr_org,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_nw_addr', $action_mod_args);
|
||||
} elsif ($chg_field eq 'nw_dst') { #SET_NW_DST
|
||||
($nw_addr_org, $ok_org) = NF2::IP_hdr::getIP($chg_val);
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_NW_DST'},
|
||||
len => $ofp->sizeof('ofp_action_nw_addr'),
|
||||
nw_addr => $nw_addr_org,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_nw_addr', $action_mod_args);
|
||||
} elsif ($chg_field eq 'nw_tos') { #SET_NW_TOS
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_NW_TOS'},
|
||||
len => $ofp->sizeof('ofp_action_nw_tos'),
|
||||
nw_tos => $chg_val,
|
||||
pad => \@pad_3,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_nw_tos', $action_mod_args);
|
||||
} elsif ($chg_field eq 'tp_src') { #SET_TP_SRC
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_TP_SRC'},
|
||||
len => $ofp->sizeof('ofp_action_tp_port'),
|
||||
tp_port => $chg_val,
|
||||
pad => \@pad_2,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_tp_port', $action_mod_args);
|
||||
} elsif ($chg_field eq 'tp_dst') { #SET_TP_DST
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_TP_DST'},
|
||||
len => $ofp->sizeof('ofp_action_tp_port'),
|
||||
tp_port => $chg_val,
|
||||
pad => \@pad_2,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_tp_port', $action_mod_args);
|
||||
} elsif ($chg_field eq 'strip_vlan') { #STRIP_VLAN
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_STRIP_VLAN'},
|
||||
len => $ofp->sizeof('ofp_action_header'),
|
||||
pad => \@pad_4,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_header', $action_mod_args);
|
||||
} elsif ($chg_field eq 'vlan_vid') { #SET_VLAN_VID
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_VLAN_VID'},
|
||||
len => $ofp->sizeof('ofp_action_vlan_vid'),
|
||||
vlan_vid => $chg_val,
|
||||
pad => \@pad_2,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_vlan_vid', $action_mod_args);
|
||||
} elsif ($chg_field eq 'vlan_pcp') { #SET_VLAN_PCP
|
||||
$chg_vlan_pcp_val = ($chg_val>>13) & 0x0007;
|
||||
$action_mod_args = {
|
||||
type => $enums{'OFPAT_SET_VLAN_PCP'},
|
||||
len => $ofp->sizeof('ofp_action_vlan_pcp'),
|
||||
vlan_pcp => $chg_vlan_pcp_val,
|
||||
pad => \@pad_3,
|
||||
};
|
||||
$action_mod = $ofp->pack('ofp_action_vlan_pcp', $action_mod_args);
|
||||
} else {
|
||||
$action_mod = undef;
|
||||
$action_mod = undef;
|
||||
}
|
||||
} else {
|
||||
$action_mod = undef;
|
||||
}
|
||||
|
||||
if (defined $action_mod) {
|
||||
$flow_mod_pkt = $flow_mod . $action_mod . $action_output;
|
||||
} else {
|
||||
$flow_mod_pkt = $flow_mod . $action_output;
|
||||
}
|
||||
return $flow_mod_pkt;
|
||||
if (defined $action_mod) {
|
||||
$flow_mod_pkt = $flow_mod . $action_mod . $action_output;
|
||||
} else {
|
||||
$flow_mod_pkt = $flow_mod . $action_output;
|
||||
}
|
||||
|
||||
return $flow_mod_pkt;
|
||||
}
|
||||
|
||||
sub create_flow_mod_from_udp_action {
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/perl -w
|
||||
# test_set_nw_dst
|
||||
|
||||
use strict;
|
||||
use OF::Includes;
|
||||
|
||||
sub send_expect_exact {
|
||||
my ($ofp, $sock, $options_ref, $in_port_offset, $out_port_offset, $max_idle, $pkt_len) = @_;
|
||||
|
||||
my $in_port = $in_port_offset + $$options_ref{'port_base'};
|
||||
my $out_port = $out_port_offset + $$options_ref{'port_base'};
|
||||
|
||||
# in_port refers to the flow mod entry's input
|
||||
|
||||
# Create the payload ourselves to make sure the two packets match
|
||||
# Jean II
|
||||
my $pkt_payload = [map {int(rand(256))} (1..($pkt_len - 8 - 4 - 16 - 14))];
|
||||
|
||||
# This is the packet we are sending... - Jean II
|
||||
my $test_pkt_args = {
|
||||
DA => "00:00:00:00:00:0" . ($out_port + 1),
|
||||
SA => "00:00:00:00:00:0" . ($in_port + 1),
|
||||
src_ip => "192.168.200." . ($in_port + 1),
|
||||
dst_ip => "192.168.201." . ($out_port + 1),
|
||||
ttl => 64,
|
||||
len => $pkt_len,
|
||||
src_port => 1,
|
||||
dst_port => 0,
|
||||
data => $pkt_payload
|
||||
};
|
||||
my $test_pkt = new NF2::UDP_pkt(%$test_pkt_args);
|
||||
|
||||
# This is the packet we are expecting to receive - Jean II
|
||||
my $expect_pkt_args = {
|
||||
DA => "00:00:00:00:00:0" . ($out_port + 1),
|
||||
SA => "00:00:00:00:00:0" . ($in_port + 1),
|
||||
src_ip => "192.168.200." . ($in_port + 1),
|
||||
dst_ip => ($out_port + 1) . ".201.168.192",
|
||||
ttl => 64,
|
||||
len => $pkt_len,
|
||||
src_port => 1,
|
||||
dst_port => 0,
|
||||
data => $pkt_payload
|
||||
};
|
||||
my $expect_pkt = new NF2::UDP_pkt(%$expect_pkt_args);
|
||||
|
||||
#print HexDump ($test_pkt->packed);
|
||||
|
||||
my $wildcards = 0x0; # exact match
|
||||
my $flags = $enums{'OFPFF_SEND_FLOW_EXP'}; # want flow expiry
|
||||
|
||||
# Get to the IP address in the expected packet - Jean II
|
||||
my $ref_to_ip_hdr = ( $expect_pkt->{'IP_hdr'} );
|
||||
my $ip_hdr_bytes = $$ref_to_ip_hdr->{'bytes'};
|
||||
my @dst_ip_subarray = @{$ip_hdr_bytes}[ 16 .. 19 ];
|
||||
my $dst_ip_inverted = ((2**24) * $dst_ip_subarray[0]
|
||||
+ (2**16) * $dst_ip_subarray[1]
|
||||
+ (2**8) * $dst_ip_subarray[2]
|
||||
+ $dst_ip_subarray[3]);
|
||||
|
||||
my $flow_mod_pkt = create_flow_mod_from_udp_action($ofp, $test_pkt, $in_port, $out_port, $max_idle, $flags, $wildcards, 'OFPFC_ADD', 'nw_dst', $dst_ip_inverted);
|
||||
|
||||
#print HexDump($flow_mod_pkt);
|
||||
|
||||
# Send 'flow_mod' message
|
||||
print $sock $flow_mod_pkt;
|
||||
print "sent flow_mod message\n";
|
||||
|
||||
# Give OF switch time to process the flow mod
|
||||
usleep($$options_ref{'send_delay'});
|
||||
|
||||
# Send a packet - ensure packet comes out desired port
|
||||
nftest_send("eth" . ($in_port_offset + 1), $test_pkt->packed);
|
||||
nftest_expect("eth" . ($out_port_offset + 1), $expect_pkt->packed);
|
||||
}
|
||||
|
||||
sub test_set_nw_dst {
|
||||
my ($ofp, $sock, $options_ref, $i, $j, $wildcards) = @_;
|
||||
|
||||
my $max_idle = $$options_ref{'max_idle'};
|
||||
my $pkt_len = $$options_ref{'pkt_len'};
|
||||
my $pkt_total = $$options_ref{'pkt_total'};
|
||||
|
||||
send_expect_exact($ofp, $sock, $options_ref, $i, $j, $max_idle, $pkt_len);
|
||||
wait_for_flow_expired($ofp, $sock, $options_ref, $pkt_len, $pkt_total);
|
||||
}
|
||||
|
||||
sub my_test {
|
||||
my ($sock, $options_ref) = @_;
|
||||
|
||||
# send from every port to every other port
|
||||
for_all_port_pairs($ofp, $sock, $options_ref, \&test_set_nw_dst, 0x0);
|
||||
}
|
||||
|
||||
run_black_box_test(\&my_test, \@ARGV);
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/perl -w
|
||||
# test_set_nw_tos
|
||||
|
||||
use strict;
|
||||
use OF::Includes;
|
||||
|
||||
sub send_expect_exact {
|
||||
my ($ofp, $sock, $options_ref, $in_port_offset, $out_port_offset, $max_idle, $pkt_len) = @_;
|
||||
|
||||
my $in_port = $in_port_offset + $$options_ref{'port_base'};
|
||||
my $out_port = $out_port_offset + $$options_ref{'port_base'};
|
||||
|
||||
# in_port refers to the flow mod entry's input
|
||||
|
||||
# Create the payload ourselves to make sure the two packets match
|
||||
# Jean II
|
||||
my $pkt_payload = [map {int(rand(256))} (1..($pkt_len - 8 - 4 - 16 - 14))];
|
||||
|
||||
# This is the packet we are sending... - Jean II
|
||||
my $test_pkt_args = {
|
||||
DA => "00:00:00:00:00:0" . ($out_port + 1),
|
||||
SA => "00:00:00:00:00:0" . ($in_port + 1),
|
||||
src_ip => "192.168.200." . ($in_port + 1),
|
||||
dst_ip => "192.168.201." . ($out_port + 1),
|
||||
tos => 0xa9,
|
||||
ttl => 64,
|
||||
len => $pkt_len,
|
||||
src_port => 1,
|
||||
dst_port => 0,
|
||||
data => $pkt_payload
|
||||
};
|
||||
my $test_pkt = new NF2::UDP_pkt(%$test_pkt_args);
|
||||
|
||||
# This is the packet we are expecting to receive - Jean II
|
||||
my $expect_pkt_args = {
|
||||
DA => "00:00:00:00:00:0" . ($out_port + 1),
|
||||
SA => "00:00:00:00:00:0" . ($in_port + 1),
|
||||
src_ip => "192.168.200." . ($in_port + 1),
|
||||
dst_ip => "192.168.201." . ($out_port + 1),
|
||||
tos => 0x55,
|
||||
ttl => 64,
|
||||
len => $pkt_len,
|
||||
src_port => 1,
|
||||
dst_port => 0,
|
||||
data => $pkt_payload
|
||||
};
|
||||
my $expect_pkt = new NF2::UDP_pkt(%$expect_pkt_args);
|
||||
|
||||
#print HexDump ($test_pkt->packed);
|
||||
|
||||
my $wildcards = 0x0; # exact match
|
||||
my $flags = $enums{'OFPFF_SEND_FLOW_EXP'}; # want flow expiry
|
||||
my $nw_tos = 0x56;
|
||||
|
||||
my $flow_mod_pkt = create_flow_mod_from_udp_action($ofp, $test_pkt, $in_port, $out_port, $max_idle, $flags, $wildcards, 'OFPFC_ADD', 'nw_tos', $nw_tos);
|
||||
|
||||
#print HexDump($flow_mod_pkt);
|
||||
|
||||
# Send 'flow_mod' message
|
||||
print $sock $flow_mod_pkt;
|
||||
print "sent flow_mod message\n";
|
||||
|
||||
# Give OF switch time to process the flow mod
|
||||
usleep($$options_ref{'send_delay'});
|
||||
|
||||
# Send a packet - ensure packet comes out desired port
|
||||
nftest_send("eth" . ($in_port_offset + 1), $test_pkt->packed);
|
||||
nftest_expect("eth" . ($out_port_offset + 1), $expect_pkt->packed);
|
||||
}
|
||||
|
||||
sub test_set_nw_tos {
|
||||
my ($ofp, $sock, $options_ref, $i, $j, $wildcards) = @_;
|
||||
|
||||
my $max_idle = $$options_ref{'max_idle'};
|
||||
my $pkt_len = $$options_ref{'pkt_len'};
|
||||
my $pkt_total = $$options_ref{'pkt_total'};
|
||||
|
||||
send_expect_exact($ofp, $sock, $options_ref, $i, $j, $max_idle, $pkt_len);
|
||||
wait_for_flow_expired($ofp, $sock, $options_ref, $pkt_len, $pkt_total);
|
||||
}
|
||||
|
||||
sub my_test {
|
||||
my ($sock, $options_ref) = @_;
|
||||
|
||||
# send from every port to every other port
|
||||
for_all_port_pairs( $ofp, $sock, $options_ref, \&test_set_nw_tos, 0x0);
|
||||
}
|
||||
|
||||
run_black_box_test(\&my_test, \@ARGV);
|
||||
@@ -34,6 +34,8 @@ test_drop_exact/run.pl
|
||||
test_forward_exact_modify_action/run.pl
|
||||
test_forward_wildcard_modify_action/run.pl
|
||||
test_flow_mod_check/run.pl
|
||||
test_set_nw_dst/run.pl
|
||||
test_set_nw_tos/run.pl
|
||||
|
||||
## ICMP handling Tests
|
||||
test_forward_exact_icmp_port/run.pl
|
||||
|
||||
@@ -197,6 +197,33 @@ set_nw_addr(struct ofpbuf *buffer, struct sw_flow_key *key,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_nw_tos(struct ofpbuf *buffer, struct sw_flow_key *key,
|
||||
const struct ofp_action_header *ah)
|
||||
{
|
||||
struct ofp_action_nw_tos *nt = (struct ofp_action_nw_tos *)ah;
|
||||
uint16_t eth_proto = ntohs(key->flow.dl_type);
|
||||
|
||||
if (eth_proto == ETH_TYPE_IP) {
|
||||
struct ip_header *nh = buffer->l3;
|
||||
uint8_t new, *field;
|
||||
|
||||
/* JeanII : Set only 6 bits, don't clobber ECN */
|
||||
new = (nt->nw_tos & 0xFC) | (nh->ip_tos & 0x03);
|
||||
|
||||
/* Get address of field */
|
||||
field = &nh->ip_tos;
|
||||
|
||||
/* jklee : ip tos field is not included in TCP pseudo header.
|
||||
* Need magic as update_csum() don't work with 8 bits. */
|
||||
nh->ip_csum = recalc_csum32(nh->ip_csum, htons((uint16_t)*field),
|
||||
htons((uint16_t)new));
|
||||
|
||||
/* Change the IP ToS bits */
|
||||
*field = new;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_tp_port(struct ofpbuf *buffer, struct sw_flow_key *key,
|
||||
const struct ofp_action_header *ah)
|
||||
@@ -283,6 +310,12 @@ static const struct openflow_action of_actions[] = {
|
||||
NULL,
|
||||
set_nw_addr
|
||||
},
|
||||
[OFPAT_SET_NW_TOS] = {
|
||||
sizeof(struct ofp_action_nw_tos),
|
||||
sizeof(struct ofp_action_nw_tos),
|
||||
NULL,
|
||||
set_nw_tos
|
||||
},
|
||||
[OFPAT_SET_TP_SRC] = {
|
||||
sizeof(struct ofp_action_tp_port),
|
||||
sizeof(struct ofp_action_tp_port),
|
||||
|
||||
@@ -410,6 +410,9 @@ Modifies the destination mac address on a packet, e.g., actions=mod_dl_dst:12:34
|
||||
.IP \fBmod_dl_src\fR:\fIsrc_mac\fR
|
||||
Modifies the source mac address on a packet, e.g., actions=mod_dl_src:12:34:56:78:9a:bc
|
||||
|
||||
.IP \fBmod_nw_tos\fR:\fItos/dscp\fR
|
||||
Modifies the ToS/DSCP (only 6-bits, not modify reserved 2-bits for future use) field of IPv4 header on a packet.
|
||||
|
||||
.IP \fBstrip_vlan\fR
|
||||
Strips the VLAN tag from a packet if it is present.
|
||||
.RE
|
||||
|
||||
+6
-3
@@ -694,9 +694,8 @@ do_dump_tables(const struct settings *s UNUSED, int argc UNUSED, char *argv[])
|
||||
dump_trivial_stats_transaction(argv[1], OFPST_TABLE);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
str_to_u32(const char *str)
|
||||
str_to_u32(const char *str)
|
||||
{
|
||||
char *tail;
|
||||
uint32_t value;
|
||||
@@ -806,7 +805,11 @@ str_to_action(char *str, struct ofpbuf *b)
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (!strcasecmp(act, "mod_vlan_vid")) {
|
||||
if (!strcasecmp(act, "mod_nw_tos")) {
|
||||
struct ofp_action_nw_tos *va;
|
||||
va = put_action(b, sizeof *va, OFPAT_SET_NW_TOS);
|
||||
va->nw_tos = str_to_u32(arg);
|
||||
} else if (!strcasecmp(act, "mod_vlan_vid")) {
|
||||
struct ofp_action_vlan_vid *va;
|
||||
va = put_action(b, sizeof *va, OFPAT_SET_VLAN_VID);
|
||||
va->vlan_vid = htons(str_to_u32(arg));
|
||||
|
||||
@@ -99,12 +99,13 @@ static const value_string names_ofp_action_type[] = {
|
||||
{ OFPAT_SET_DL_DST, "Ethernet destination address" },
|
||||
{ OFPAT_SET_NW_SRC, "IP source address" },
|
||||
{ OFPAT_SET_NW_DST, "IP destination address" },
|
||||
{ OFPAT_SET_NW_TOS, "Set IP TOS field" },
|
||||
{ OFPAT_SET_TP_SRC, "TCP/UDP source port" },
|
||||
{ OFPAT_SET_TP_DST, "TCP/UDP destination port"},
|
||||
{ OFPAT_VENDOR, "Vendor-defined action"},
|
||||
{ 0, NULL }
|
||||
};
|
||||
#define NUM_ACTIONS_FLAGS 10
|
||||
#define NUM_ACTIONS_FLAGS 11
|
||||
#define NUM_PORT_CONFIG_FLAGS 7
|
||||
#define NUM_PORT_STATE_FLAGS 1
|
||||
#define NUM_PORT_FEATURES_FLAGS 12
|
||||
@@ -414,6 +415,7 @@ static gint ofp_action_vlan_vid = -1;
|
||||
static gint ofp_action_vlan_pcp = -1;
|
||||
static gint ofp_action_dl_addr = -1;
|
||||
static gint ofp_action_nw_addr = -1;
|
||||
static gint ofp_action_nw_tos = -1;
|
||||
static gint ofp_action_tp_port = -1;
|
||||
static gint ofp_action_vendor = -1;
|
||||
static gint ofp_action_unknown = -1;
|
||||
@@ -1076,6 +1078,9 @@ void proto_register_openflow()
|
||||
{ &ofp_action_nw_addr,
|
||||
{ "IP Addr", "of.action_nw_addr", FT_IPv4, BASE_NONE, NO_STRINGS, NO_MASK, "IP Addr", HFILL }},
|
||||
|
||||
{ &ofp_action_nw_tos,
|
||||
{ "IP TOS bits", "of.action_vlan_pcp", FT_UINT8, BASE_DEC, NO_STRINGS, NO_MASK, "IP TOS bits", HFILL }},
|
||||
|
||||
{ &ofp_action_tp_port,
|
||||
{ "Port", "of.action_tp_port", FT_UINT16, BASE_DEC, NO_STRINGS, NO_MASK, "TCP/UDP Port", HFILL }},
|
||||
|
||||
@@ -1169,9 +1174,12 @@ void proto_register_openflow()
|
||||
{ " IP destination address", "of.sf_actions_ip_dst_addr", FT_UINT32, BASE_DEC, VALS(names_choice), 1 << OFPAT_SET_NW_DST, "IP destination address", HFILL }},
|
||||
|
||||
{ &ofp_switch_features_actions[8],
|
||||
{ " TCP/UDP source", "of.sf_actions_src_port", FT_UINT32, BASE_DEC, VALS(names_choice), 1 << OFPAT_SET_TP_SRC, "TCP/UDP source port", HFILL }},
|
||||
{ " Set IP TOS bits", "of.sf_actions_ip_tos", FT_UINT32, BASE_DEC, VALS(names_choice), 1 << OFPAT_SET_NW_TOS, "Set IP TOS bits", HFILL }},
|
||||
|
||||
{ &ofp_switch_features_actions[9],
|
||||
{ " TCP/UDP source", "of.sf_actions_src_port", FT_UINT32, BASE_DEC, VALS(names_choice), 1 << OFPAT_SET_TP_SRC, "TCP/UDP source port", HFILL }},
|
||||
|
||||
{ &ofp_switch_features_actions[10],
|
||||
{ " TCP/UDP destination", "of.sf_actions_dst_port", FT_UINT32, BASE_DEC, VALS(names_choice), 1 << OFPAT_SET_TP_DST, "TCP/UDP destination port", HFILL }},
|
||||
|
||||
{ &ofp_switch_features_ports_hdr,
|
||||
@@ -2221,6 +2229,11 @@ static gint dissect_action(proto_tree* tree, proto_item* item, tvbuff_t *tvb, pa
|
||||
add_child( action_tree, ofp_action_nw_addr, tvb, offset, 4 );
|
||||
break;
|
||||
|
||||
case OFPAT_SET_NW_TOS:
|
||||
add_child( action_tree, ofp_action_nw_tos, tvb, offset, 1);
|
||||
dissect_pad(action_tree, offset, 3);
|
||||
break;
|
||||
|
||||
case OFPAT_SET_TP_SRC:
|
||||
case OFPAT_SET_TP_DST:
|
||||
add_child( action_tree, ofp_action_tp_port, tvb, offset, 2 );
|
||||
|
||||
Reference in New Issue
Block a user