netlink-socket: Reduce nl_sock_recv() from 2 (or more) system calls to 1.
[sliver-openvswitch.git] / lib / dpif-netdev.c
index 5005270..3b93a4c 100644 (file)
@@ -114,7 +114,7 @@ struct dp_netdev_flow {
     long long int used;         /* Last used time, in monotonic msecs. */
     long long int packet_count; /* Number of packets matched. */
     long long int byte_count;   /* Number of bytes matched. */
-    uint16_t tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
+    ovs_be16 tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
 
     /* Actions. */
     struct nlattr *actions;
@@ -708,7 +708,6 @@ dpif_netdev_validate_actions(const struct nlattr *actions,
             break;
 
         case ODP_ACTION_ATTR_CONTROLLER:
-        case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
             break;
 
         case ODP_ACTION_ATTR_SET_DL_TCI:
@@ -944,6 +943,7 @@ dpif_netdev_flow_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_)
 
 static int
 dpif_netdev_execute(struct dpif *dpif,
+                    const struct nlattr *key_attrs, size_t key_len,
                     const struct nlattr *actions, size_t actions_len,
                     const struct ofpbuf *packet)
 {
@@ -975,7 +975,10 @@ dpif_netdev_execute(struct dpif *dpif,
          * if we don't. */
         copy = *packet;
     }
+
     flow_extract(&copy, 0, -1, &key);
+    dpif_netdev_flow_from_nlattrs(key_attrs, key_len, &key);
+
     error = dp_netdev_execute_actions(dp, &copy, &key, actions, actions_len);
     if (mutates) {
         ofpbuf_uninit(&copy);
@@ -1174,7 +1177,7 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, const struct flow *key,
         struct ip_header *nh = packet->l3;
         ovs_be32 ip = nl_attr_get_be32(a);
         uint16_t type = nl_attr_type(a);
-        uint32_t *field;
+        ovs_be32 *field;
 
         field = type == ODP_ACTION_ATTR_SET_NW_SRC ? &nh->ip_src : &nh->ip_dst;
         if (key->nw_proto == IPPROTO_TCP && packet->l7) {
@@ -1185,7 +1188,7 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, const struct flow *key,
             if (uh->udp_csum) {
                 uh->udp_csum = recalc_csum32(uh->udp_csum, *field, ip);
                 if (!uh->udp_csum) {
-                    uh->udp_csum = 0xffff;
+                    uh->udp_csum = htons(0xffff);
                 }
             }
         }
@@ -1218,7 +1221,7 @@ dp_netdev_set_tp_port(struct ofpbuf *packet, const struct flow *key,
        if (is_ip(packet, key)) {
         uint16_t type = nl_attr_type(a);
         ovs_be16 port = nl_attr_get_be16(a);
-        uint16_t *field;
+        ovs_be16 *field;
 
         if (key->nw_proto == IPPROTO_TCP && packet->l7) {
             struct tcp_header *th = packet->l4;
@@ -1281,34 +1284,6 @@ dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet,
     return 0;
 }
 
-/* Returns true if 'packet' is an invalid Ethernet+IPv4 ARP packet: one with
- * 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 flow *key)
-{
-    struct arp_eth_header *arp;
-    struct eth_header *eth;
-    ptrdiff_t l3_size;
-
-    if (key->dl_type != htons(ETH_TYPE_ARP)) {
-        return false;
-    }
-
-    l3_size = (char *) ofpbuf_end(packet) - (char *) packet->l3;
-    if (l3_size < sizeof(struct arp_eth_header)) {
-        return true;
-    }
-
-    eth = packet->l2;
-    arp = packet->l3;
-    return (arp->ar_hrd != htons(ARP_HRD_ETHERNET)
-            || arp->ar_pro != htons(ARP_PRO_IP)
-            || arp->ar_hln != ETH_HEADER_LEN
-            || arp->ar_pln != 4
-            || !eth_addr_equals(arp->ar_sha, eth->eth_src));
-}
-
 static int
 dp_netdev_execute_actions(struct dp_netdev *dp,
                           struct ofpbuf *packet, struct flow *key,
@@ -1358,11 +1333,6 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
         case ODP_ACTION_ATTR_SET_TP_DST:
             dp_netdev_set_tp_port(packet, key, a);
             break;
-
-        case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
-            if (dp_netdev_is_spoofed_arp(packet, key)) {
-                return 0;
-            }
         }
     }
     return 0;