Remove netdev_find_dev_by_in4
[sliver-openvswitch.git] / lib / packets.c
index 83c852c..815d4e6 100644 (file)
@@ -75,36 +75,54 @@ compose_benign_packet(struct ofpbuf *b, const char *tag, uint16_t snap_type,
     memcpy(payload + tag_size, eth_src, ETH_ADDR_LEN);
 }
 
-/* Modify the TCI field of 'packet', whose data must begin with an Ethernet
- * header.  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'.
+/* Insert VLAN header according to given TCI. Packet passed must be Ethernet
+ * packet.
  *
  * Also sets 'packet->l2' to point to the new Ethernet header. */
 void
-eth_set_vlan_tci(struct ofpbuf *packet, ovs_be16 tci)
+eth_push_vlan(struct ofpbuf *packet, ovs_be16 tci)
 {
     struct eth_header *eh = packet->data;
     struct vlan_eth_header *veh;
 
-    if (packet->size >= sizeof(struct vlan_eth_header)
-        && eh->eth_type == htons(ETH_TYPE_VLAN)) {
-        veh = packet->data;
-        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);
-        tmp.veth_tci = tci;
-        tmp.veth_next_type = eh->eth_type;
-
-        veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
-        memcpy(veh, &tmp, sizeof tmp);
-    }
+    /* 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 = tci;
+    tmp.veth_next_type = eh->eth_type;
+
+    veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
+    memcpy(veh, &tmp, sizeof tmp);
+
     packet->l2 = packet->data;
 }
 
+/* Given the IP netmask 'netmask', returns the number of bits of the IP address
+ * that it specifies, that is, the number of 1-bits in 'netmask'.  'netmask'
+ * must be a CIDR netmask (see ip_is_cidr()). */
+int
+ip_count_cidr_bits(ovs_be32 netmask)
+{
+    assert(ip_is_cidr(netmask));
+    return 32 - ctz(ntohl(netmask));
+}
+
+void
+ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *s)
+{
+    ds_put_format(s, IP_FMT, IP_ARGS(&ip));
+    if (mask != htonl(UINT32_MAX)) {
+        if (ip_is_cidr(mask)) {
+            ds_put_format(s, "/%d", ip_count_cidr_bits(mask));
+        } else {
+            ds_put_format(s, "/"IP_FMT, IP_ARGS(&mask));
+        }
+    }
+}
+
+
 /* Stores the string representation of the IPv6 address 'addr' into the
  * character array 'addr_str', which must be at least INET6_ADDRSTRLEN
  * bytes long. */
@@ -117,10 +135,29 @@ format_ipv6_addr(char *addr_str, const struct in6_addr *addr)
 void
 print_ipv6_addr(struct ds *string, const struct in6_addr *addr)
 {
-    char addr_str[INET6_ADDRSTRLEN];
+    char *dst;
 
-    format_ipv6_addr(addr_str, addr);
-    ds_put_format(string, "%s", addr_str);
+    ds_reserve(string, string->length + INET6_ADDRSTRLEN);
+
+    dst = string->string + string->length;
+    format_ipv6_addr(dst, addr);
+    string->length += strlen(dst);
+}
+
+void
+print_ipv6_masked(struct ds *s, const struct in6_addr *addr,
+                  const struct in6_addr *mask)
+{
+    print_ipv6_addr(s, addr);
+    if (mask && !ipv6_mask_is_exact(mask)) {
+        if (ipv6_is_cidr(mask)) {
+            int cidr_bits = ipv6_count_cidr_bits(mask);
+            ds_put_format(s, "/%d", cidr_bits);
+        } else {
+            ds_put_char(s, '/');
+            print_ipv6_addr(s, mask);
+        }
+    }
 }
 
 struct in6_addr ipv6_addr_bitand(const struct in6_addr *a,
@@ -164,9 +201,9 @@ ipv6_create_mask(int mask)
     return netmask;
 }
 
-/* Given the IPv6 netmask 'netmask', returns the number of bits of the
- * IPv6 address that it wildcards.  'netmask' must be a CIDR netmask (see
- * ipv6_is_cidr()). */
+/* Given the IPv6 netmask 'netmask', returns the number of bits of the IPv6
+ * address that it specifies, that is, the number of 1-bits in 'netmask'.
+ * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()). */
 int
 ipv6_count_cidr_bits(const struct in6_addr *netmask)
 {
@@ -221,7 +258,10 @@ ipv6_is_cidr(const struct in6_addr *netmask)
 /* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',
  * 'eth_src' and 'eth_type' parameters.  A payload of 'size' bytes is allocated
  * in 'b' and returned.  This payload may be populated with appropriate
- * information by the caller. */
+ * information by the caller.
+ *
+ * The returned packet has enough headroom to insert an 802.1Q VLAN header if
+ * desired. */
 void *
 eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
             const uint8_t eth_src[ETH_ADDR_LEN], uint16_t eth_type,
@@ -232,7 +272,8 @@ eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
 
     ofpbuf_clear(b);
 
-    ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + size);
+    ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN + size);
+    ofpbuf_reserve(b, VLAN_HEADER_LEN);
     eth = ofpbuf_put_uninit(b, ETH_HEADER_LEN);
     data = ofpbuf_put_uninit(b, size);
 
@@ -246,7 +287,10 @@ eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
 /* Populates 'b' with an Ethernet LLC+SNAP packet headed with the given
  * 'eth_dst', 'eth_src', 'snap_org', and 'snap_type'.  A payload of 'size'
  * bytes is allocated in 'b' and returned.  This payload may be populated with
- * appropriate information by the caller. */
+ * appropriate information by the caller.
+ *
+ * The returned packet has enough headroom to insert an 802.1Q VLAN header if
+ * desired. */
 void *
 snap_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
              const uint8_t eth_src[ETH_ADDR_LEN],
@@ -259,7 +303,9 @@ snap_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
     /* Compose basic packet structure.  (We need the payload size to stick into
      * the 802.2 header.) */
     ofpbuf_clear(b);
-    ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + LLC_SNAP_HEADER_LEN + size);
+    ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN
+                             + LLC_SNAP_HEADER_LEN + size);
+    ofpbuf_reserve(b, VLAN_HEADER_LEN);
     eth = ofpbuf_put_zeros(b, ETH_HEADER_LEN);
     llc_snap = ofpbuf_put_zeros(b, LLC_SNAP_HEADER_LEN);
     payload = ofpbuf_put_uninit(b, size);
@@ -280,46 +326,3 @@ snap_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN],
 
     return payload;
 }
-
-/* Populates 'pdu' with a LACP PDU comprised of 'actor' and 'partner'. */
-void
-compose_lacp_pdu(const struct lacp_info *actor,
-                 const struct lacp_info *partner, struct lacp_pdu *pdu)
-{
-    memset(pdu, 0, sizeof *pdu);
-
-    pdu->subtype = 1;
-    pdu->version = 1;
-
-    pdu->actor_type = 1;
-    pdu->actor_len = 20;
-    pdu->actor = *actor;
-
-    pdu->partner_type = 2;
-    pdu->partner_len = 20;
-    pdu->partner = *partner;
-
-    pdu->collector_type = 3;
-    pdu->collector_len = 16;
-    pdu->collector_delay = htons(0);
-}
-
-/* Parses 'b' which represents a packet containing a LACP PDU.  This function
- * returns NULL if 'b' is malformed, or does not represent a LACP PDU format
- * supported by OVS.  Otherwise, it returns a pointer to the lacp_pdu contained
- * within 'b'. */
-const struct lacp_pdu *
-parse_lacp_packet(const struct ofpbuf *b)
-{
-    const struct lacp_pdu *pdu;
-
-    pdu = ofpbuf_at(b, (uint8_t *)b->l3 - (uint8_t *)b->data, LACP_PDU_LEN);
-
-    if (pdu && pdu->subtype == 1
-        && pdu->actor_type == 1 && pdu->actor_len == 20
-        && pdu->partner_type == 2 && pdu->partner_len == 20) {
-        return pdu;
-    } else {
-        return NULL;
-    }
-}