Skip to content

Commit 6a54ded

Browse files
committed
odp-netlink.h: Use 32-bit aligned 64-bit types.
Open vSwitch userspace uses special types to indicate that a particular object may not be naturally aligned. Netlink is one source of such problems: in Netlink, 64-bit integers are often aligned only on 32-bit boundaries. This commit changes the odp-netlink.h that is transformed from <linux/openvswitch.h> to use these types to make it harder to accidentally access a misaligned 64-bit member. Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Jesse Gross <jesse@nicira.com>
1 parent 837eefc commit 6a54ded

3 files changed

Lines changed: 47 additions & 40 deletions

File tree

build-aux/extract-odp-netlink-h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,22 @@
1414
# Avoid using reserved names in header guards.
1515
s/_LINUX_OPENVSWITCH_H/ODP_NETLINK_H/
1616

17-
# Transform Linux-specific __u<N> types into C99 uint<N>_t types,
18-
# and Linux-specific __be<N> into Open vSwitch ovs_be<N>,
17+
# Transform most Linux-specific __u<N> types into C99 uint<N>_t types,
18+
# and most Linux-specific __be<N> into Open vSwitch ovs_be<N>,
1919
# and use the appropriate userspace header.
2020
s,<linux/types\.h>,"openvswitch/types.h",
21-
s/__u64/uint64_t/g
2221
s/__u32/uint32_t/g
2322
s/__u16/uint16_t/g
2423
s/__u8/uint8_t/g
25-
s/__be64/ovs_be64/g
2624
s/__be32/ovs_be32/g
2725
s/__be16/ovs_be16/g
2826

27+
# Transform 64-bit Linux-specific types into Open vSwitch specialized
28+
# types for 64-bit numbers that might only be aligned on a 32-bit
29+
# boundary.
30+
s/__u64/ovs_32aligned_u64/g
31+
s/__be64/ovs_32aligned_be64/g
32+
2933
# Use OVS's own ETH_ADDR_LEN instead of Linux-specific ETH_ALEN.
3034
s,<linux/if_ether\.h>,"packets.h",
3135
s/ETH_ALEN/ETH_ADDR_LEN/

lib/dpif-linux.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ struct dpif_linux_dp {
7373
const char *name; /* OVS_DP_ATTR_NAME. */
7474
const uint32_t *upcall_pid; /* OVS_DP_ATTR_UPCALL_PID. */
7575
uint32_t user_features; /* OVS_DP_ATTR_USER_FEATURES */
76-
struct ovs_dp_stats stats; /* OVS_DP_ATTR_STATS. */
77-
struct ovs_dp_megaflow_stats megaflow_stats;
76+
const struct ovs_dp_stats *stats; /* OVS_DP_ATTR_STATS. */
77+
const struct ovs_dp_megaflow_stats *megaflow_stats;
7878
/* OVS_DP_ATTR_MEGAFLOW_STATS.*/
7979
};
8080

@@ -554,12 +554,23 @@ dpif_linux_get_stats(const struct dpif *dpif_, struct dpif_dp_stats *stats)
554554

555555
error = dpif_linux_dp_get(dpif_, &dp, &buf);
556556
if (!error) {
557-
stats->n_hit = dp.stats.n_hit;
558-
stats->n_missed = dp.stats.n_missed;
559-
stats->n_lost = dp.stats.n_lost;
560-
stats->n_flows = dp.stats.n_flows;
561-
stats->n_masks = dp.megaflow_stats.n_masks;
562-
stats->n_mask_hit = dp.megaflow_stats.n_mask_hit;
557+
memset(stats, 0, sizeof *stats);
558+
559+
if (dp.stats) {
560+
stats->n_hit = get_32aligned_u64(&dp.stats->n_hit);
561+
stats->n_missed = get_32aligned_u64(&dp.stats->n_missed);
562+
stats->n_lost = get_32aligned_u64(&dp.stats->n_lost);
563+
stats->n_flows = get_32aligned_u64(&dp.stats->n_flows);
564+
}
565+
566+
if (dp.megaflow_stats) {
567+
stats->n_masks = dp.megaflow_stats->n_masks;
568+
stats->n_mask_hit = get_32aligned_u64(
569+
&dp.megaflow_stats->n_mask_hit);
570+
} else {
571+
stats->n_masks = UINT32_MAX;
572+
stats->n_mask_hit = UINT64_MAX;
573+
}
563574
ofpbuf_delete(buf);
564575
}
565576
return error;
@@ -2203,17 +2214,11 @@ dpif_linux_dp_from_ofpbuf(struct dpif_linux_dp *dp, const struct ofpbuf *buf)
22032214
dp->dp_ifindex = ovs_header->dp_ifindex;
22042215
dp->name = nl_attr_get_string(a[OVS_DP_ATTR_NAME]);
22052216
if (a[OVS_DP_ATTR_STATS]) {
2206-
/* Can't use structure assignment because Netlink doesn't ensure
2207-
* sufficient alignment for 64-bit members. */
2208-
memcpy(&dp->stats, nl_attr_get(a[OVS_DP_ATTR_STATS]),
2209-
sizeof dp->stats);
2217+
dp->stats = nl_attr_get(a[OVS_DP_ATTR_STATS]);
22102218
}
22112219

22122220
if (a[OVS_DP_ATTR_MEGAFLOW_STATS]) {
2213-
/* Can't use structure assignment because Netlink doesn't ensure
2214-
* sufficient alignment for 64-bit members. */
2215-
memcpy(&dp->megaflow_stats, nl_attr_get(a[OVS_DP_ATTR_MEGAFLOW_STATS]),
2216-
sizeof dp->megaflow_stats);
2221+
dp->megaflow_stats = nl_attr_get(a[OVS_DP_ATTR_MEGAFLOW_STATS]);
22172222
}
22182223

22192224
return 0;
@@ -2252,8 +2257,6 @@ static void
22522257
dpif_linux_dp_init(struct dpif_linux_dp *dp)
22532258
{
22542259
memset(dp, 0, sizeof *dp);
2255-
dp->megaflow_stats.n_masks = UINT32_MAX;
2256-
dp->megaflow_stats.n_mask_hit = UINT64_MAX;
22572260
}
22582261

22592262
static void
@@ -2473,8 +2476,8 @@ dpif_linux_flow_get_stats(const struct dpif_linux_flow *flow,
24732476
struct dpif_flow_stats *stats)
24742477
{
24752478
if (flow->stats) {
2476-
stats->n_packets = get_unaligned_u64(&flow->stats->n_packets);
2477-
stats->n_bytes = get_unaligned_u64(&flow->stats->n_bytes);
2479+
stats->n_packets = get_32aligned_u64(&flow->stats->n_packets);
2480+
stats->n_bytes = get_32aligned_u64(&flow->stats->n_bytes);
24782481
} else {
24792482
stats->n_packets = 0;
24802483
stats->n_bytes = 0;

lib/netdev-linux.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,14 +1499,14 @@ static void
14991499
netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst,
15001500
const struct ovs_vport_stats *src)
15011501
{
1502-
dst->rx_packets = get_unaligned_u64(&src->rx_packets);
1503-
dst->tx_packets = get_unaligned_u64(&src->tx_packets);
1504-
dst->rx_bytes = get_unaligned_u64(&src->rx_bytes);
1505-
dst->tx_bytes = get_unaligned_u64(&src->tx_bytes);
1506-
dst->rx_errors = get_unaligned_u64(&src->rx_errors);
1507-
dst->tx_errors = get_unaligned_u64(&src->tx_errors);
1508-
dst->rx_dropped = get_unaligned_u64(&src->rx_dropped);
1509-
dst->tx_dropped = get_unaligned_u64(&src->tx_dropped);
1502+
dst->rx_packets = get_32aligned_u64(&src->rx_packets);
1503+
dst->tx_packets = get_32aligned_u64(&src->tx_packets);
1504+
dst->rx_bytes = get_32aligned_u64(&src->rx_bytes);
1505+
dst->tx_bytes = get_32aligned_u64(&src->tx_bytes);
1506+
dst->rx_errors = get_32aligned_u64(&src->rx_errors);
1507+
dst->tx_errors = get_32aligned_u64(&src->tx_errors);
1508+
dst->rx_dropped = get_32aligned_u64(&src->rx_dropped);
1509+
dst->tx_dropped = get_32aligned_u64(&src->tx_dropped);
15101510
dst->multicast = 0;
15111511
dst->collisions = 0;
15121512
dst->rx_length_errors = 0;
@@ -1701,14 +1701,14 @@ netdev_internal_set_stats(struct netdev *netdev,
17011701
struct dpif_linux_vport vport;
17021702
int err;
17031703

1704-
vport_stats.rx_packets = stats->rx_packets;
1705-
vport_stats.tx_packets = stats->tx_packets;
1706-
vport_stats.rx_bytes = stats->rx_bytes;
1707-
vport_stats.tx_bytes = stats->tx_bytes;
1708-
vport_stats.rx_errors = stats->rx_errors;
1709-
vport_stats.tx_errors = stats->tx_errors;
1710-
vport_stats.rx_dropped = stats->rx_dropped;
1711-
vport_stats.tx_dropped = stats->tx_dropped;
1704+
put_32aligned_u64(&vport_stats.rx_packets, stats->rx_packets);
1705+
put_32aligned_u64(&vport_stats.tx_packets, stats->tx_packets);
1706+
put_32aligned_u64(&vport_stats.rx_bytes, stats->rx_bytes);
1707+
put_32aligned_u64(&vport_stats.tx_bytes, stats->tx_bytes);
1708+
put_32aligned_u64(&vport_stats.rx_errors, stats->rx_errors);
1709+
put_32aligned_u64(&vport_stats.tx_errors, stats->tx_errors);
1710+
put_32aligned_u64(&vport_stats.rx_dropped, stats->rx_dropped);
1711+
put_32aligned_u64(&vport_stats.tx_dropped, stats->tx_dropped);
17121712

17131713
dpif_linux_vport_init(&vport);
17141714
vport.cmd = OVS_VPORT_CMD_SET;

0 commit comments

Comments
 (0)