projects
/
openvswitch
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
datapath: Add loop detection for RT kernels.
[openvswitch]
/
lib
/
dpif-netdev.c
diff --git
a/lib/dpif-netdev.c
b/lib/dpif-netdev.c
index 11ad370ff1da8965707fa3b726fc0950b8bd68d5..3df6598d25ae3fbba0015fd3e1bb5ebf004d3daf 100644
(file)
--- a/
lib/dpif-netdev.c
+++ b/
lib/dpif-netdev.c
@@
-94,7
+94,7
@@
struct dp_netdev_port {
/* A flow in dp_netdev's 'flow_table'. */
struct dp_netdev_flow {
struct hmap_node node; /* Element in dp_netdev's 'flow_table'. */
/* A flow in dp_netdev's 'flow_table'. */
struct dp_netdev_flow {
struct hmap_node node; /* Element in dp_netdev's 'flow_table'. */
-
flow_t
key;
+
struct flow
key;
/* Statistics. */
struct timespec used; /* Last used time. */
/* Statistics. */
struct timespec used; /* Last used time. */
@@
-135,7
+135,7
@@
static int do_del_port(struct dp_netdev *, uint16_t port_no);
static int dp_netdev_output_control(struct dp_netdev *, const struct ofpbuf *,
int queue_no, int port_no, uint32_t arg);
static int dp_netdev_execute_actions(struct dp_netdev *,
static int dp_netdev_output_control(struct dp_netdev *, const struct ofpbuf *,
int queue_no, int port_no, uint32_t arg);
static int dp_netdev_execute_actions(struct dp_netdev *,
- struct ofpbuf *,
const flow_t
*,
+ struct ofpbuf *,
struct flow
*,
const union odp_action *, int n);
static struct dpif_netdev *
const union odp_action *, int n);
static struct dpif_netdev *
@@
-588,11
+588,10
@@
dpif_netdev_port_poll_wait(const struct dpif *dpif_)
}
static struct dp_netdev_flow *
}
static struct dp_netdev_flow *
-dp_netdev_lookup_flow(const struct dp_netdev *dp, const
flow_t
*key)
+dp_netdev_lookup_flow(const struct dp_netdev *dp, const
struct flow
*key)
{
struct dp_netdev_flow *flow;
{
struct dp_netdev_flow *flow;
- assert(!key->reserved[0] && !key->reserved[1] && !key->reserved[2]);
HMAP_FOR_EACH_WITH_HASH (flow, node, flow_hash(key, 0), &dp->flow_table) {
if (flow_equal(&flow->key, key)) {
return flow;
HMAP_FOR_EACH_WITH_HASH (flow, node, flow_hash(key, 0), &dp->flow_table) {
if (flow_equal(&flow->key, key)) {
return flow;
@@
-601,12
+600,12
@@
dp_netdev_lookup_flow(const struct dp_netdev *dp, const flow_t *key)
return NULL;
}
return NULL;
}
+/* The caller must fill in odp_flow->key itself. */
static void
answer_flow_query(struct dp_netdev_flow *flow, uint32_t query_flags,
struct odp_flow *odp_flow)
{
if (flow) {
static void
answer_flow_query(struct dp_netdev_flow *flow, uint32_t query_flags,
struct odp_flow *odp_flow)
{
if (flow) {
- odp_flow->key = flow->key;
odp_flow->stats.n_packets = flow->packet_count;
odp_flow->stats.n_bytes = flow->byte_count;
odp_flow->stats.used_sec = flow->used.tv_sec;
odp_flow->stats.n_packets = flow->packet_count;
odp_flow->stats.n_bytes = flow->byte_count;
odp_flow->stats.used_sec = flow->used.tv_sec;
@@
-638,7
+637,10
@@
dpif_netdev_flow_get(const struct dpif *dpif, struct odp_flow flows[], int n)
for (i = 0; i < n; i++) {
struct odp_flow *odp_flow = &flows[i];
for (i = 0; i < n; i++) {
struct odp_flow *odp_flow = &flows[i];
- answer_flow_query(dp_netdev_lookup_flow(dp, &odp_flow->key),
+ struct flow key;
+
+ odp_flow_key_to_flow(&odp_flow->key, &key);
+ answer_flow_query(dp_netdev_lookup_flow(dp, &key),
odp_flow->flags, odp_flow);
}
return 0;
odp_flow->flags, odp_flow);
}
return 0;
@@
-663,16
+665,9
@@
dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
case ODPAT_CONTROLLER:
break;
case ODPAT_CONTROLLER:
break;
- case ODPAT_SET_
VLAN_VID
:
+ case ODPAT_SET_
DL_TCI
:
*mutates = true;
*mutates = true;
- if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) {
- return EINVAL;
- }
- break;
-
- case ODPAT_SET_VLAN_PCP:
- *mutates = true;
- if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
+ if (a->dl_tci.tci & htons(VLAN_CFI)) {
return EINVAL;
}
break;
return EINVAL;
}
break;
@@
-732,8
+727,7
@@
add_flow(struct dpif *dpif, struct odp_flow *odp_flow)
int error;
flow = xzalloc(sizeof *flow);
int error;
flow = xzalloc(sizeof *flow);
- flow->key = odp_flow->key;
- memset(flow->key.reserved, 0, sizeof flow->key.reserved);
+ odp_flow_key_to_flow(&odp_flow->key, &flow->key);
error = set_flow_actions(flow, odp_flow);
if (error) {
error = set_flow_actions(flow, odp_flow);
if (error) {
@@
-760,8
+754,10
@@
dpif_netdev_flow_put(struct dpif *dpif, struct odp_flow_put *put)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
+ struct flow key;
- flow = dp_netdev_lookup_flow(dp, &put->flow.key);
+ odp_flow_key_to_flow(&put->flow.key, &key);
+ flow = dp_netdev_lookup_flow(dp, &key);
if (!flow) {
if (put->flags & ODPPF_CREATE) {
if (hmap_count(&dp->flow_table) < MAX_FLOWS) {
if (!flow) {
if (put->flags & ODPPF_CREATE) {
if (hmap_count(&dp->flow_table) < MAX_FLOWS) {
@@
-791,8
+787,10
@@
dpif_netdev_flow_del(struct dpif *dpif, struct odp_flow *odp_flow)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
+ struct flow key;
- flow = dp_netdev_lookup_flow(dp, &odp_flow->key);
+ odp_flow_key_to_flow(&odp_flow->key, &key);
+ flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
answer_flow_query(flow, 0, odp_flow);
dp_netdev_free_flow(dp, flow);
if (flow) {
answer_flow_query(flow, 0, odp_flow);
dp_netdev_free_flow(dp, flow);
@@
-814,7
+812,10
@@
dpif_netdev_flow_list(const struct dpif *dpif, struct odp_flow flows[], int n)
if (i >= n) {
break;
}
if (i >= n) {
break;
}
- answer_flow_query(flow, 0, &flows[i++]);
+
+ odp_flow_key_from_flow(&flows[i].key, &flow->key);
+ answer_flow_query(flow, 0, &flows[i]);
+ i++;
}
return hmap_count(&dp->flow_table);
}
}
return hmap_count(&dp->flow_table);
}
@@
-827,7
+828,7
@@
dpif_netdev_execute(struct dpif *dpif,
struct dp_netdev *dp = get_dp_netdev(dpif);
struct ofpbuf copy;
bool mutates;
struct dp_netdev *dp = get_dp_netdev(dpif);
struct ofpbuf copy;
bool mutates;
-
flow_t flow
;
+
struct flow key
;
int error;
if (packet->size < ETH_HEADER_LEN || packet->size > UINT16_MAX) {
int error;
if (packet->size < ETH_HEADER_LEN || packet->size > UINT16_MAX) {
@@
-852,8
+853,8
@@
dpif_netdev_execute(struct dpif *dpif,
* if we don't. */
copy = *packet;
}
* if we don't. */
copy = *packet;
}
- flow_extract(©, 0, -1, &
flow
);
- error = dp_netdev_execute_actions(dp, ©, &
flow
, actions, n_actions);
+ flow_extract(©, 0, -1, &
key
);
+ error = dp_netdev_execute_actions(dp, ©, &
key
, actions, n_actions);
if (mutates) {
ofpbuf_uninit(©);
}
if (mutates) {
ofpbuf_uninit(©);
}
@@
-922,7
+923,7
@@
dpif_netdev_recv_wait(struct dpif *dpif)
}
\f
static void
}
\f
static void
-dp_netdev_flow_used(struct dp_netdev_flow *flow,
const flow_t
*key,
+dp_netdev_flow_used(struct dp_netdev_flow *flow,
struct flow
*key,
const struct ofpbuf *packet)
{
time_timespec(&flow->used);
const struct ofpbuf *packet)
{
time_timespec(&flow->used);
@@
-939,7
+940,7
@@
dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
struct ofpbuf *packet)
{
struct dp_netdev_flow *flow;
struct ofpbuf *packet)
{
struct dp_netdev_flow *flow;
-
flow_t
key;
+
struct flow
key;
if (packet->size < ETH_HEADER_LEN) {
return;
if (packet->size < ETH_HEADER_LEN) {
return;
@@
-1005,16
+1006,12
@@
dp_netdev_wait(void)
}
}
-/* Modify the TCI field of 'packet'. If a VLAN tag is not present, one
- * is added with the TCI field set to 'tci'. If a VLAN tag is present,
- * then 'mask' bits are cleared before 'tci' is logically OR'd into the
- * TCI field.
- *
- * Note that the function does not ensure that 'tci' does not affect
- * bits outside of 'mask'.
+/* Modify the TCI field of 'packet'. If a VLAN tag is present, its TCI field
+ * is replaced by 'tci'. If a VLAN tag is not present, one is added with the
+ * TCI field set to 'tci'.
*/
static void
*/
static void
-dp_netdev_
modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask
)
+dp_netdev_
set_dl_tci(struct ofpbuf *packet, uint16_t tci
)
{
struct vlan_eth_header *veh;
struct eth_header *eh;
{
struct vlan_eth_header *veh;
struct eth_header *eh;
@@
-1022,17
+1019,15
@@
dp_netdev_modify_vlan_tci(struct ofpbuf *packet, uint16_t tci, uint16_t mask)
eh = packet->l2;
if (packet->size >= sizeof(struct vlan_eth_header)
&& eh->eth_type == htons(ETH_TYPE_VLAN)) {
eh = packet->l2;
if (packet->size >= sizeof(struct vlan_eth_header)
&& eh->eth_type == htons(ETH_TYPE_VLAN)) {
- /* Clear 'mask' bits, but maintain other TCI bits. */
veh = packet->l2;
veh = packet->l2;
- veh->veth_tci &= ~htons(mask);
- veh->veth_tci |= htons(tci);
+ veh->veth_tci = tci;
} else {
/* Insert new 802.1Q header. */
struct vlan_eth_header tmp;
memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
tmp.veth_type = htons(ETH_TYPE_VLAN);
} else {
/* Insert new 802.1Q header. */
struct vlan_eth_header tmp;
memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
tmp.veth_type = htons(ETH_TYPE_VLAN);
- tmp.veth_tci =
htons(tci)
;
+ tmp.veth_tci =
tci
;
tmp.veth_next_type = eh->eth_type;
veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
tmp.veth_next_type = eh->eth_type;
veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
@@
-1075,13
+1070,13
@@
dp_netdev_set_dl_dst(struct ofpbuf *packet, const uint8_t dl_addr[ETH_ADDR_LEN])
}
static bool
}
static bool
-is_ip(const struct ofpbuf *packet, const
flow_t
*key)
+is_ip(const struct ofpbuf *packet, const
struct flow
*key)
{
return key->dl_type == htons(ETH_TYPE_IP) && packet->l4;
}
static void
{
return key->dl_type == htons(ETH_TYPE_IP) && packet->l4;
}
static void
-dp_netdev_set_nw_addr(struct ofpbuf *packet,
const flow_t
*key,
+dp_netdev_set_nw_addr(struct ofpbuf *packet,
struct flow
*key,
const struct odp_action_nw_addr *a)
{
if (is_ip(packet, key)) {
const struct odp_action_nw_addr *a)
{
if (is_ip(packet, key)) {
@@
-1107,7
+1102,7
@@
dp_netdev_set_nw_addr(struct ofpbuf *packet, const flow_t *key,
}
static void
}
static void
-dp_netdev_set_nw_tos(struct ofpbuf *packet,
const flow_t
*key,
+dp_netdev_set_nw_tos(struct ofpbuf *packet,
struct flow
*key,
const struct odp_action_nw_tos *a)
{
if (is_ip(packet, key)) {
const struct odp_action_nw_tos *a)
{
if (is_ip(packet, key)) {
@@
-1124,7
+1119,7
@@
dp_netdev_set_nw_tos(struct ofpbuf *packet, const flow_t *key,
}
static void
}
static void
-dp_netdev_set_tp_port(struct ofpbuf *packet,
const flow_t
*key,
+dp_netdev_set_tp_port(struct ofpbuf *packet,
struct flow
*key,
const struct odp_action_tp_port *a)
{
if (is_ip(packet, key)) {
const struct odp_action_tp_port *a)
{
if (is_ip(packet, key)) {
@@
-1186,7
+1181,7
@@
dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet,
* screwy or truncated header fields or one whose inner and outer Ethernet
* address differ. */
static bool
* screwy or truncated header fields or one whose inner and outer Ethernet
* address differ. */
static bool
-dp_netdev_is_spoofed_arp(struct ofpbuf *packet, const struct
odp_flow_key
*key)
+dp_netdev_is_spoofed_arp(struct ofpbuf *packet, const struct
flow
*key)
{
struct arp_eth_header *arp;
struct eth_header *eth;
{
struct arp_eth_header *arp;
struct eth_header *eth;
@@
-1212,7
+1207,7
@@
dp_netdev_is_spoofed_arp(struct ofpbuf *packet, const struct odp_flow_key *key)
static int
dp_netdev_execute_actions(struct dp_netdev *dp,
static int
dp_netdev_execute_actions(struct dp_netdev *dp,
- struct ofpbuf *packet,
const flow_t
*key,
+ struct ofpbuf *packet,
struct flow
*key,
const union odp_action *actions, int n_actions)
{
int i;
const union odp_action *actions, int n_actions)
{
int i;
@@
-1229,15
+1224,8
@@
dp_netdev_execute_actions(struct dp_netdev *dp,
key->in_port, a->controller.arg);
break;
key->in_port, a->controller.arg);
break;
- case ODPAT_SET_VLAN_VID:
- dp_netdev_modify_vlan_tci(packet, ntohs(a->vlan_vid.vlan_vid),
- VLAN_VID_MASK);
- break;
-
- case ODPAT_SET_VLAN_PCP:
- dp_netdev_modify_vlan_tci(packet,
- a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
- VLAN_PCP_MASK);
+ case ODPAT_SET_DL_TCI:
+ dp_netdev_set_dl_tci(packet, a->dl_tci.tci);
break;
case ODPAT_STRIP_VLAN:
break;
case ODPAT_STRIP_VLAN: