Process RARP packets with ethertype 0x8035 similar to ARP packets.
[openvswitch] / lib / ofp-util.c
index 0f49cdcf94822fdd6fc15f13b436435caccf78cd..b81476869610ce16a050e047d517bec9b96c89d1 100644 (file)
@@ -305,7 +305,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
     uint16_t wc = ntohl(ofmatch->wildcards);
     uint8_t dl_src_mask[ETH_ADDR_LEN];
     uint8_t dl_dst_mask[ETH_ADDR_LEN];
-    bool ipv4, arp;
+    bool ipv4, arp, rarp;
     int i;
 
     match_init_catchall(match);
@@ -370,6 +370,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
 
     ipv4 = match->flow.dl_type == htons(ETH_TYPE_IP);
     arp = match->flow.dl_type == htons(ETH_TYPE_ARP);
+    rarp = match->flow.dl_type == htons(ETH_TYPE_RARP);
 
     if (ipv4 && !(wc & OFPFW11_NW_TOS)) {
         if (ofmatch->nw_tos & ~IP_DSCP_MASK) {
@@ -380,7 +381,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
         match_set_nw_dscp(match, ofmatch->nw_tos);
     }
 
-    if (ipv4 || arp) {
+    if (ipv4 || arp || rarp) {
         if (!(wc & OFPFW11_NW_PROTO)) {
             match_set_nw_proto(match, ofmatch->nw_proto);
         }
@@ -1157,7 +1158,6 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
             fm->cookie_mask = htonll(0);
             fm->new_cookie = ofm->cookie;
         } else {
-            /* XXX */
             fm->cookie = ofm->cookie;
             fm->cookie_mask = ofm->cookie_mask;
             fm->new_cookie = htonll(UINT64_MAX);
@@ -1284,7 +1284,11 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD, OFP12_VERSION,
                            NXM_TYPICAL_LEN + fm->ofpacts_len);
         ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
-        ofm->cookie = fm->new_cookie;
+        if (fm->command == OFPFC_ADD) {
+            ofm->cookie = fm->new_cookie;
+        } else {
+            ofm->cookie = fm->cookie;
+        }
         ofm->cookie_mask = fm->cookie_mask;
         ofm->table_id = fm->table_id;
         ofm->command = fm->command;
@@ -3539,34 +3543,35 @@ ofputil_check_output_port(uint16_t port, int max_ports)
         OFPUTIL_NAMED_PORT(LOCAL)               \
         OFPUTIL_NAMED_PORT(NONE)
 
-/* Returns the port number represented by 's', which may be an integer or, for
- * reserved ports, the standard OpenFlow name for the port (e.g. "LOCAL").
+/* Stores the port number represented by 's' into '*portp'.  's' may be an
+ * integer or, for reserved ports, the standard OpenFlow name for the port
+ * (e.g. "LOCAL").
  *
- * Returns 0 if 's' is not a valid OpenFlow port number or name.  The caller
- * should issue an error message in this case, because this function usually
- * does not.  (This gives the caller an opportunity to look up the port name
- * another way, e.g. by contacting the switch and listing the names of all its
- * ports).
+ * Returns true if successful, false if 's' is not a valid OpenFlow port number
+ * or name.  The caller should issue an error message in this case, because
+ * this function usually does not.  (This gives the caller an opportunity to
+ * look up the port name another way, e.g. by contacting the switch and listing
+ * the names of all its ports).
  *
  * This function accepts OpenFlow 1.0 port numbers.  It also accepts a subset
  * of OpenFlow 1.1+ port numbers, mapping those port numbers into the 16-bit
  * range as described in include/openflow/openflow-1.1.h. */
-uint16_t
-ofputil_port_from_string(const char *s)
+bool
+ofputil_port_from_string(const char *s, uint16_t *portp)
 {
     unsigned int port32;
 
+    *portp = 0;
     if (str_to_uint(s, 10, &port32)) {
-        if (port32 == 0) {
-            VLOG_WARN("port 0 is not a valid OpenFlow port number");
-            return 0;
-        } else if (port32 < OFPP_MAX) {
-            return port32;
+        if (port32 < OFPP_MAX) {
+            *portp = port32;
+            return true;
         } else if (port32 < OFPP_FIRST_RESV) {
             VLOG_WARN("port %u is a reserved OF1.0 port number that will "
                       "be translated to %u when talking to an OF1.1 or "
                       "later controller", port32, port32 + OFPP11_OFFSET);
-            return port32;
+            *portp = port32;
+            return true;
         } else if (port32 <= OFPP_LAST_RESV) {
             struct ds s;
 
@@ -3577,14 +3582,16 @@ ofputil_port_from_string(const char *s)
                            ds_cstr(&s), port32);
             ds_destroy(&s);
 
-            return port32;
+            *portp = port32;
+            return true;
         } else if (port32 < OFPP11_MAX) {
             VLOG_WARN("port %u is outside the supported range 0 through "
                       "%"PRIx16"or 0x%x through 0x%"PRIx32, port32,
                       UINT16_MAX, (unsigned int) OFPP11_MAX, UINT32_MAX);
-            return 0;
+            return false;
         } else {
-            return port32 - OFPP11_OFFSET;
+            *portp = port32 - OFPP11_OFFSET;
+            return true;
         }
     } else {
         struct pair {
@@ -3600,10 +3607,11 @@ ofputil_port_from_string(const char *s)
 
         for (p = pairs; p < &pairs[ARRAY_SIZE(pairs)]; p++) {
             if (!strcasecmp(s, p->name)) {
-                return p->value;
+                *portp = p->value;
+                return true;
             }
         }
-        return 0;
+        return false;
     }
 }
 
@@ -3782,7 +3790,8 @@ ofputil_normalize_match__(struct match *match, bool may_log)
                 may_match |= MAY_ND_TARGET | MAY_ARP_THA;
             }
         }
-    } else if (match->flow.dl_type == htons(ETH_TYPE_ARP)) {
+    } else if (match->flow.dl_type == htons(ETH_TYPE_ARP) ||
+               match->flow.dl_type == htons(ETH_TYPE_RARP)) {
         may_match = MAY_NW_PROTO | MAY_NW_ADDR | MAY_ARP_SHA | MAY_ARP_THA;
     } else {
         may_match = 0;