ofproto: Add support for matching IP addresses in ARP header (OpenFlow 1.0)
[sliver-openvswitch.git] / lib / vconn.c
index 85fbb26..546c600 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -859,12 +859,14 @@ make_flow_mod(uint16_t command, const flow_t *flow, size_t actions_len)
     ofm->header.version = OFP_VERSION;
     ofm->header.type = OFPT_FLOW_MOD;
     ofm->header.length = htons(size);
+    ofm->cookie = 0;
     ofm->match.wildcards = htonl(0);
     ofm->match.in_port = htons(flow->in_port == ODPP_LOCAL ? OFPP_LOCAL
                                : flow->in_port);
     memcpy(ofm->match.dl_src, flow->dl_src, sizeof ofm->match.dl_src);
     memcpy(ofm->match.dl_dst, flow->dl_dst, sizeof ofm->match.dl_dst);
     ofm->match.dl_vlan = flow->dl_vlan;
+    ofm->match.dl_vlan_pcp = flow->dl_vlan_pcp;
     ofm->match.dl_type = flow->dl_type;
     ofm->match.nw_src = flow->nw_src;
     ofm->match.nw_dst = flow->nw_dst;
@@ -1045,7 +1047,7 @@ check_ofp_message(const struct ofp_header *msg, uint8_t type, size_t size)
                      "received %s message of length %zu (expected %zu)",
                      type_name, got_size, size);
         free(type_name);
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
 
     return 0;
@@ -1081,7 +1083,7 @@ check_ofp_message_array(const struct ofp_header *msg, uint8_t type,
                      "(expected at least %zu)",
                      type_name, got_size, min_size);
         free(type_name);
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     if ((got_size - min_size) % array_elt_size) {
         char *type_name = ofp_message_type_to_string(type);
@@ -1092,7 +1094,7 @@ check_ofp_message_array(const struct ofp_header *msg, uint8_t type,
                      type_name, got_size, min_size, got_size - min_size,
                      array_elt_size, (got_size - min_size) % array_elt_size);
         free(type_name);
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     if (n_array_elts) {
         *n_array_elts = (got_size - min_size) / array_elt_size;
@@ -1122,13 +1124,13 @@ check_ofp_packet_out(const struct ofp_header *oh, struct ofpbuf *data,
         VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %u bytes of actions "
                      "but message has room for only %zu bytes",
                      actions_len, extra);
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     if (actions_len % sizeof(union ofp_action)) {
         VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %u bytes of actions, "
                      "which is not a multiple of %zu",
                      actions_len, sizeof(union ofp_action));
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
 
     n_actions = actions_len / sizeof(union ofp_action);
@@ -1265,6 +1267,7 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports)
     case OFPAT_STRIP_VLAN:
     case OFPAT_SET_NW_SRC:
     case OFPAT_SET_NW_DST:
+    case OFPAT_SET_NW_TOS:
     case OFPAT_SET_TP_SRC:
     case OFPAT_SET_TP_DST:
         return check_action_exact_len(a, len, 8);
@@ -1282,7 +1285,8 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports)
         break;
 
     default:
-        VLOG_WARN_RL(&bad_ofmsg_rl, "unknown action type %"PRIu16, a->type);
+        VLOG_WARN_RL(&bad_ofmsg_rl, "unknown action type %"PRIu16,
+                ntohs(a->type));
         return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE);
     }
 
@@ -1394,6 +1398,17 @@ normalize_match(struct ofp_match *m)
         if (wc & OFPFW_NW_DST_MASK) {
             m->nw_dst &= flow_nw_bits_to_mask(wc, OFPFW_NW_DST_SHIFT);
         }
+    } else if (m->dl_type == htons(ETH_TYPE_ARP)) {
+        if (wc & OFPFW_NW_PROTO) {
+            m->nw_proto = 0;
+        }
+        if (wc & OFPFW_NW_SRC_MASK) {
+            m->nw_src &= flow_nw_bits_to_mask(wc, OFPFW_NW_SRC_SHIFT);
+        }
+        if (wc & OFPFW_NW_DST_MASK) {
+            m->nw_dst &= flow_nw_bits_to_mask(wc, OFPFW_NW_DST_SHIFT);
+        }
+        m->tp_src = m->tp_dst = 0;
     } else {
         /* Network and transport layer fields will always be extracted as
          * zeros, so we can do an exact-match on those values. */