diff --git a/lib/cfm.c b/lib/cfm.c index 48556cf1a..dcdaa0ea6 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -557,7 +557,7 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet, eth_push_vlan(packet, htons(ETH_TYPE_VLAN), htons(tci)); } - ccm = packet->l3; + ccm = ofpbuf_get_l3(packet); ccm->mdlevel_version = 0; ccm->opcode = CCM_OPCODE; ccm->tlv_offset = 70; @@ -719,7 +719,8 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) ovs_mutex_lock(&mutex); eth = p->l2; - ccm = ofpbuf_at(p, (uint8_t *)p->l3 - (uint8_t *)p->data, CCM_ACCEPT_LEN); + ccm = ofpbuf_at(p, (uint8_t *)ofpbuf_get_l3(p) - (uint8_t *)p->data, + CCM_ACCEPT_LEN); if (!ccm) { VLOG_INFO_RL(&rl, "%s: Received an unparseable 802.1ag CCM heartbeat.", diff --git a/lib/flow.c b/lib/flow.c index 4e8cc0e07..314c1c768 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -338,18 +338,20 @@ invalid: /* Initializes 'flow' members from 'packet' and 'md' * - * Initializes 'packet' header pointers as follows: + * Initializes 'packet' header l2 pointer to the start of the Ethernet + * header, and the layer offsets as follows: * - * - packet->l2 to the start of the Ethernet header. + * - packet->l2_5_ofs to the start of the MPLS shim header, or UINT16_MAX + * when there is no MPLS shim header. * - * - packet->l2_5 to the start of the MPLS shim header. - * - * - packet->l3 to just past the Ethernet header, or just past the + * - packet->l3_ofs to just past the Ethernet header, or just past the * vlan_header if one is present, to the first byte of the payload of the - * Ethernet frame. + * Ethernet frame. UINT16_MAX if the frame is too short to contain an + * Ethernet header. * - * - packet->l4 to just past the IPv4 header, if one is present and has a - * correct length, and otherwise NULL. + * - packet->l4_ofs to just past the IPv4 header, if one is present and + * has at least the content used for the fields of interest for the flow, + * otherwise UINT16_MAX. */ void flow_extract(struct ofpbuf *packet, const struct pkt_metadata *md, @@ -370,9 +372,9 @@ flow_extract(struct ofpbuf *packet, const struct pkt_metadata *md, } packet->l2 = b.data; - packet->l2_5 = NULL; - packet->l3 = NULL; - packet->l4 = NULL; + ofpbuf_set_l2_5(packet, NULL); + ofpbuf_set_l3(packet, NULL); + ofpbuf_set_l4(packet, NULL); if (b.size < sizeof *eth) { return; @@ -392,16 +394,16 @@ flow_extract(struct ofpbuf *packet, const struct pkt_metadata *md, /* Parse mpls, copy l3 ttl. */ if (eth_type_mpls(flow->dl_type)) { - packet->l2_5 = b.data; + ofpbuf_set_l2_5(packet, b.data); parse_mpls(&b, flow); } /* Network layer. */ - packet->l3 = b.data; + ofpbuf_set_l3(packet, b.data); if (flow->dl_type == htons(ETH_TYPE_IP)) { const struct ip_header *nh = pull_ip(&b); if (nh) { - packet->l4 = b.data; + ofpbuf_set_l4(packet, b.data); flow->nw_src = get_16aligned_be32(&nh->ip_src); flow->nw_dst = get_16aligned_be32(&nh->ip_dst); @@ -437,7 +439,7 @@ flow_extract(struct ofpbuf *packet, const struct pkt_metadata *md, return; } - packet->l4 = b.data; + ofpbuf_set_l4(packet, b.data); if (flow->nw_proto == IPPROTO_TCP) { parse_tcp(&b, flow); } else if (flow->nw_proto == IPPROTO_UDP) { @@ -1237,45 +1239,48 @@ flow_set_mpls_lse(struct flow *flow, int idx, ovs_be32 lse) flow->mpls_lse[idx] = lse; } -static uint8_t * +static size_t flow_compose_l4(struct ofpbuf *b, const struct flow *flow) { + size_t l4_len = 0; + if (!(flow->nw_frag & FLOW_NW_FRAG_ANY) || !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { if (flow->nw_proto == IPPROTO_TCP) { struct tcp_header *tcp; - tcp = ofpbuf_put_zeros(b, sizeof *tcp); + l4_len = sizeof *tcp; + tcp = ofpbuf_put_zeros(b, l4_len); tcp->tcp_src = flow->tp_src; tcp->tcp_dst = flow->tp_dst; tcp->tcp_ctl = TCP_CTL(ntohs(flow->tcp_flags), 5); - return ofpbuf_tail(b); } else if (flow->nw_proto == IPPROTO_UDP) { struct udp_header *udp; - udp = ofpbuf_put_zeros(b, sizeof *udp); + l4_len = sizeof *udp; + udp = ofpbuf_put_zeros(b, l4_len); udp->udp_src = flow->tp_src; udp->udp_dst = flow->tp_dst; - return ofpbuf_tail(b); } else if (flow->nw_proto == IPPROTO_SCTP) { struct sctp_header *sctp; - sctp = ofpbuf_put_zeros(b, sizeof *sctp); + l4_len = sizeof *sctp; + sctp = ofpbuf_put_zeros(b, l4_len); sctp->sctp_src = flow->tp_src; sctp->sctp_dst = flow->tp_dst; - return ofpbuf_tail(b); } else if (flow->nw_proto == IPPROTO_ICMP) { struct icmp_header *icmp; - icmp = ofpbuf_put_zeros(b, sizeof *icmp); + l4_len = sizeof *icmp; + icmp = ofpbuf_put_zeros(b, l4_len); icmp->icmp_type = ntohs(flow->tp_src); icmp->icmp_code = ntohs(flow->tp_dst); icmp->icmp_csum = csum(icmp, ICMP_HEADER_LEN); - return ofpbuf_tail(b); } else if (flow->nw_proto == IPPROTO_ICMPV6) { struct icmp6_hdr *icmp; - icmp = ofpbuf_put_zeros(b, sizeof *icmp); + l4_len = sizeof *icmp; + icmp = ofpbuf_put_zeros(b, l4_len); icmp->icmp6_type = ntohs(flow->tp_src); icmp->icmp6_code = ntohs(flow->tp_dst); @@ -1285,16 +1290,19 @@ flow_compose_l4(struct ofpbuf *b, const struct flow *flow) struct in6_addr *nd_target; struct nd_opt_hdr *nd_opt; + l4_len += sizeof *nd_target; nd_target = ofpbuf_put_zeros(b, sizeof *nd_target); *nd_target = flow->nd_target; if (!eth_addr_is_zero(flow->arp_sha)) { + l4_len += 8; nd_opt = ofpbuf_put_zeros(b, 8); nd_opt->nd_opt_len = 1; nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; memcpy(nd_opt + 1, flow->arp_sha, ETH_ADDR_LEN); } if (!eth_addr_is_zero(flow->arp_tha)) { + l4_len += 8; nd_opt = ofpbuf_put_zeros(b, 8); nd_opt->nd_opt_len = 1; nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; @@ -1303,10 +1311,9 @@ flow_compose_l4(struct ofpbuf *b, const struct flow *flow) } icmp->icmp6_cksum = (OVS_FORCE uint16_t) csum(icmp, (char *)ofpbuf_tail(b) - (char *)icmp); - return ofpbuf_tail(b); } } - return NULL; + return l4_len; } /* Puts into 'b' a packet that flow_extract() would parse as having the given @@ -1318,6 +1325,8 @@ flow_compose_l4(struct ofpbuf *b, const struct flow *flow) void flow_compose(struct ofpbuf *b, const struct flow *flow) { + size_t l4_len; + /* eth_compose() sets l3 pointer and makes sure it is 32-bit aligned. */ eth_compose(b, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0); if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) { @@ -1348,16 +1357,14 @@ flow_compose(struct ofpbuf *b, const struct flow *flow) } } - b->l4 = ofpbuf_tail(b); + ofpbuf_set_l4(b, ofpbuf_tail(b)); - flow_compose_l4(b, flow); + l4_len = flow_compose_l4(b, flow); - ip->ip_tot_len = htons((uint8_t *) b->data + b->size - - (uint8_t *) b->l3); + ip->ip_tot_len = htons(b->l4_ofs - b->l3_ofs + l4_len); ip->ip_csum = csum(ip, sizeof *ip); } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { struct ovs_16aligned_ip6_hdr *nh; - uint8_t *l7; nh = ofpbuf_put_zeros(b, sizeof *nh); put_16aligned_be32(&nh->ip6_flow, htonl(6 << 28) | @@ -1368,16 +1375,17 @@ flow_compose(struct ofpbuf *b, const struct flow *flow) memcpy(&nh->ip6_src, &flow->ipv6_src, sizeof(nh->ip6_src)); memcpy(&nh->ip6_dst, &flow->ipv6_dst, sizeof(nh->ip6_dst)); - b->l4 = ofpbuf_tail(b); + ofpbuf_set_l4(b, ofpbuf_tail(b)); - l7 = flow_compose_l4(b, flow); + l4_len = flow_compose_l4(b, flow); - nh->ip6_plen = l7 ? htons(l7 - (uint8_t *) b->l4) : htons(0); + nh->ip6_plen = htons(l4_len); } else if (flow->dl_type == htons(ETH_TYPE_ARP) || flow->dl_type == htons(ETH_TYPE_RARP)) { struct arp_eth_header *arp; - b->l3 = arp = ofpbuf_put_zeros(b, sizeof *arp); + arp = ofpbuf_put_zeros(b, sizeof *arp); + ofpbuf_set_l3(b, arp); arp->ar_hrd = htons(1); arp->ar_pro = htons(ETH_TYPE_IP); arp->ar_hln = ETH_ADDR_LEN; @@ -1396,7 +1404,7 @@ flow_compose(struct ofpbuf *b, const struct flow *flow) if (eth_type_mpls(flow->dl_type)) { int n; - b->l2_5 = b->l3; + b->l2_5_ofs = b->l3_ofs; for (n = 1; n < FLOW_MAX_MPLS_LABELS; n++) { if (flow->mpls_lse[n - 1] & htonl(MPLS_BOS_MASK)) { break; diff --git a/lib/lacp.c b/lib/lacp.c index cbe2259f4..711d7ec12 100644 --- a/lib/lacp.c +++ b/lib/lacp.c @@ -181,7 +181,8 @@ 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); + pdu = ofpbuf_at(b, (uint8_t *)ofpbuf_get_l3(b) - (uint8_t *)b->data, + LACP_PDU_LEN); if (pdu && pdu->subtype == 1 && pdu->actor_type == 1 && pdu->actor_len == 20 diff --git a/lib/netlink.c b/lib/netlink.c index 3f479bef8..96abe46dd 100644 --- a/lib/netlink.c +++ b/lib/netlink.c @@ -66,7 +66,7 @@ nl_msg_nlmsgerr(const struct ofpbuf *msg, int *errorp) struct nlmsgerr *err = ofpbuf_at(msg, NLMSG_HDRLEN, sizeof *err); int code = EPROTO; if (!err) { - VLOG_ERR_RL(&rl, "received invalid nlmsgerr (%"PRIuSIZE"d bytes < %"PRIuSIZE"d)", + VLOG_ERR_RL(&rl, "received invalid nlmsgerr (%"PRIu32"d bytes < %"PRIuSIZE"d)", msg->size, NLMSG_HDRLEN + sizeof *err); } else if (err->error <= 0 && err->error > INT_MIN) { code = -err->error; diff --git a/lib/nx-match.c b/lib/nx-match.c index fe6d80f7f..cd3bf0854 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -215,7 +215,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, if (!p) { VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a " "multiple of 8, is longer than space in message (max " - "length %"PRIuSIZE")", match_len, b->size); + "length %"PRIu32")", match_len, b->size); return OFPERR_OFPBMC_BAD_LEN; } } @@ -272,7 +272,7 @@ oxm_pull_match__(struct ofpbuf *b, bool strict, struct match *match) if (!p) { VLOG_DBG_RL(&rl, "oxm length %u, rounded up to a " "multiple of 8, is longer than space in message (max " - "length %"PRIuSIZE")", match_len, b->size); + "length %"PRIu32")", match_len, b->size); return OFPERR_OFPBMC_BAD_LEN; } diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 6e04816a5..e5aa0ce50 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -51,7 +51,7 @@ odp_set_tunnel_action(const struct nlattr *a, struct flow_tnl *tun_key) static void set_arp(struct ofpbuf *packet, const struct ovs_key_arp *arp_key) { - struct arp_eth_header *arp = packet->l3; + struct arp_eth_header *arp = ofpbuf_get_l3(packet); arp->ar_op = arp_key->arp_op; memcpy(arp->ar_sha, arp_key->arp_sha, ETH_ADDR_LEN); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index d552f9cfc..23d89d307 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -710,7 +710,7 @@ ofpacts_pull_openflow_actions(struct ofpbuf *openflow, actions = ofpbuf_try_pull(openflow, actions_len); if (actions == NULL) { VLOG_WARN_RL(&rl, "OpenFlow message actions length %u exceeds " - "remaining message length (%"PRIuSIZE")", + "remaining message length (%"PRIu32")", actions_len, openflow->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -1768,7 +1768,7 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow, instructions = ofpbuf_try_pull(openflow, instructions_len); if (instructions == NULL) { VLOG_WARN_RL(&rl, "OpenFlow message instructions length %u exceeds " - "remaining message length (%"PRIuSIZE")", + "remaining message length (%"PRIu32")", instructions_len, openflow->size); error = OFPERR_OFPBIC_BAD_LEN; goto exit; diff --git a/lib/ofp-msgs.c b/lib/ofp-msgs.c index 092741fd7..677d359ed 100644 --- a/lib/ofp-msgs.c +++ b/lib/ofp-msgs.c @@ -399,7 +399,8 @@ ofpraw_pull(enum ofpraw *rawp, struct ofpbuf *msg) enum ofpraw raw; /* Set default outputs. */ - msg->l2 = msg->l3 = msg->data; + msg->l2 = msg->data; + ofpbuf_set_l3(msg, msg->data); *rawp = 0; len = msg->size; @@ -416,7 +417,7 @@ ofpraw_pull(enum ofpraw *rawp, struct ofpbuf *msg) info = raw_info_get(raw); instance = raw_instance_get(info, hdrs.version); msg->l2 = ofpbuf_pull(msg, instance->hdrs_len); - msg->l3 = msg->data; + ofpbuf_set_l3(msg, msg->data); min_len = instance->hdrs_len + info->min_body; switch (info->extra_multiple) { @@ -664,7 +665,7 @@ ofpraw_put__(enum ofpraw raw, uint8_t version, ovs_be32 xid, ofpbuf_prealloc_tailroom(buf, (instance->hdrs_len + info->min_body + extra_tailroom)); buf->l2 = ofpbuf_put_uninit(buf, instance->hdrs_len); - buf->l3 = ofpbuf_tail(buf); + ofpbuf_set_l3(buf, ofpbuf_tail(buf)); oh = buf->l2; oh->version = version; @@ -893,7 +894,7 @@ ofpmp_reserve(struct list *replies, size_t len) next = ofpbuf_new(MAX(1024, hdrs_len + len)); ofpbuf_put(next, msg->data, hdrs_len); next->l2 = next->data; - next->l3 = ofpbuf_tail(next); + ofpbuf_set_l3(next, ofpbuf_tail(next)); list_push_back(replies, &next->list_node); *ofpmp_flags__(msg->data) |= htons(OFPSF_REPLY_MORE); diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 599dc322b..b88d1e7de 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -71,13 +71,13 @@ ofp_packet_to_string(const void *data, size_t len) l4_size = ofpbuf_get_l4_size(&buf); if (flow.nw_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) { - struct tcp_header *th = buf.l4; + struct tcp_header *th = ofpbuf_get_l4(&buf); ds_put_format(&ds, " tcp_csum:%"PRIx16, ntohs(th->tcp_csum)); } else if (flow.nw_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) { - struct udp_header *uh = buf.l4; + struct udp_header *uh = ofpbuf_get_l4(&buf); ds_put_format(&ds, " udp_csum:%"PRIx16, ntohs(uh->udp_csum)); } else if (flow.nw_proto == IPPROTO_SCTP && l4_size >= SCTP_HEADER_LEN) { - struct sctp_header *sh = buf.l4; + struct sctp_header *sh = ofpbuf_get_l4(&buf); ds_put_format(&ds, " sctp_csum:%"PRIx32, ntohl(sh->sctp_csum)); } diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 8e81c0130..d0002d516 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -1929,7 +1929,7 @@ ofputil_decode_meter_config(struct ofpbuf *msg, omc = ofpbuf_try_pull(msg, sizeof *omc); if (!omc) { VLOG_WARN_RL(&bad_ofmsg_rl, - "OFPMP_METER_CONFIG reply has %"PRIuSIZE" leftover bytes at end", + "OFPMP_METER_CONFIG reply has %"PRIu32" leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -2005,7 +2005,7 @@ ofputil_decode_meter_stats(struct ofpbuf *msg, oms = ofpbuf_try_pull(msg, sizeof *oms); if (!oms) { VLOG_WARN_RL(&bad_ofmsg_rl, - "OFPMP_METER reply has %"PRIuSIZE" leftover bytes at end", + "OFPMP_METER reply has %"PRIu32" leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -2176,7 +2176,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, nfm->command = ofputil_tid_command(fm, protocol); nfm->cookie = fm->new_cookie; match_len = nx_put_match(msg, &fm->match, fm->cookie, fm->cookie_mask); - nfm = msg->l3; + nfm = ofpbuf_get_l3(msg); nfm->idle_timeout = htons(fm->idle_timeout); nfm->hard_timeout = htons(fm->hard_timeout); nfm->priority = htons(fm->priority); @@ -2396,7 +2396,7 @@ ofputil_append_queue_get_config_reply(struct ofpbuf *reply, struct ofp12_packet_queue *opq12; ovs_be32 port; - qgcr11 = reply->l3; + qgcr11 = ofpbuf_get_l3(reply); port = qgcr11->port; opq12 = ofpbuf_put_zeros(reply, sizeof *opq12); @@ -2636,7 +2636,7 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr, match_len = nx_put_match(msg, &fsr->match, fsr->cookie, fsr->cookie_mask); - nfsr = msg->l3; + nfsr = ofpbuf_get_l3(msg); nfsr->out_port = htons(ofp_to_u16(fsr->out_port)); nfsr->match_len = htons(match_len); nfsr->table_id = fsr->table_id; @@ -2698,7 +2698,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, ofs = ofpbuf_try_pull(msg, sizeof *ofs); if (!ofs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIuSIZE" leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIu32" leftover " "bytes at end", msg->size); return EINVAL; } @@ -2748,7 +2748,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, ofs = ofpbuf_try_pull(msg, sizeof *ofs); if (!ofs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIuSIZE" leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIu32" leftover " "bytes at end", msg->size); return EINVAL; } @@ -2784,7 +2784,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, nfs = ofpbuf_try_pull(msg, sizeof *nfs); if (!nfs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply has %"PRIuSIZE" leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply has %"PRIu32" leftover " "bytes at end", msg->size); return EINVAL; } @@ -2982,7 +2982,7 @@ ofputil_decode_aggregate_stats_reply(struct ofputil_aggregate_stats *stats, ofpbuf_use_const(&msg, reply, ntohs(reply->length)); ofpraw_pull_assert(&msg); - asr = msg.l3; + asr = ofpbuf_get_l3(&msg); stats->packet_count = ntohll(get_32aligned_be64(&asr->packet_count)); stats->byte_count = ntohll(get_32aligned_be64(&asr->byte_count)); stats->flow_count = ntohl(asr->flow_count); @@ -3134,7 +3134,7 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr, nfr = ofpbuf_put_zeros(msg, sizeof *nfr); match_len = nx_put_match(msg, &fr->match, 0, 0); - nfr = msg->l3; + nfr = ofpbuf_get_l3(msg); nfr->cookie = fr->cookie; nfr->priority = htons(fr->priority); nfr->reason = fr->reason; @@ -3346,7 +3346,7 @@ ofputil_encode_nx_packet_in(const struct ofputil_packet_in *pin) ofpbuf_put_zeros(packet, 2); ofpbuf_put(packet, pin->packet, pin->packet_len); - npi = packet->l3; + npi = ofpbuf_get_l3(packet); npi->buffer_id = htonl(pin->buffer_id); npi->total_len = htons(pin->total_len); npi->reason = pin->reason; @@ -3410,7 +3410,7 @@ ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin, ofpbuf_put_zeros(packet, 2); ofpbuf_put(packet, pin->packet, pin->packet_len); - opi = packet->l3; + opi = ofpbuf_get_l3(packet); opi->pi.buffer_id = htonl(pin->buffer_id); opi->pi.total_len = htons(pin->total_len); opi->pi.reason = pin->reason; @@ -4629,7 +4629,7 @@ ofputil_decode_role_message(const struct ofp_header *oh, if (raw == OFPRAW_OFPT12_ROLE_REQUEST || raw == OFPRAW_OFPT12_ROLE_REPLY) { - const struct ofp12_role_request *orr = b.l3; + const struct ofp12_role_request *orr = ofpbuf_get_l3(&b); if (orr->role != htonl(OFPCR12_ROLE_NOCHANGE) && orr->role != htonl(OFPCR12_ROLE_EQUAL) && @@ -4650,7 +4650,7 @@ ofputil_decode_role_message(const struct ofp_header *oh, } } else if (raw == OFPRAW_NXT_ROLE_REQUEST || raw == OFPRAW_NXT_ROLE_REPLY) { - const struct nx_role_request *nrr = b.l3; + const struct nx_role_request *nrr = ofpbuf_get_l3(&b); BUILD_ASSERT(NX_ROLE_OTHER + 1 == OFPCR12_ROLE_EQUAL); BUILD_ASSERT(NX_ROLE_MASTER + 1 == OFPCR12_ROLE_MASTER); @@ -4739,7 +4739,7 @@ ofputil_decode_role_status(const struct ofp_header *oh, raw = ofpraw_pull_assert(&b); ovs_assert(raw == OFPRAW_OFPT14_ROLE_STATUS); - r = b.l3; + r = ofpbuf_get_l3(&b); if (r->role != htonl(OFPCR12_ROLE_NOCHANGE) && r->role != htonl(OFPCR12_ROLE_EQUAL) && r->role != htonl(OFPCR12_ROLE_MASTER) && @@ -4953,7 +4953,7 @@ ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq, nfmr = ofpbuf_try_pull(msg, sizeof *nfmr); if (!nfmr) { - VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR request has %"PRIuSIZE" " + VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR request has %"PRIu32" " "leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -5107,7 +5107,7 @@ ofputil_decode_flow_update(struct ofputil_flow_update *update, } bad_len: - VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR reply has %"PRIuSIZE" " + VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR reply has %"PRIu32" " "leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -5211,7 +5211,7 @@ ofputil_encode_packet_out(const struct ofputil_packet_out *po, ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg, ofp_version); - opo = msg->l3; + opo = ofpbuf_get_l3(msg); opo->buffer_id = htonl(po->buffer_id); opo->in_port = htons(ofp_to_u16(po->in_port)); opo->actions_len = htons(msg->size - actions_ofs); @@ -5229,7 +5229,7 @@ ofputil_encode_packet_out(const struct ofputil_packet_out *po, ofpbuf_put_zeros(msg, sizeof *opo); len = ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg, ofp_version); - opo = msg->l3; + opo = ofpbuf_get_l3(msg); opo->buffer_id = htonl(po->buffer_id); opo->in_port = ofputil_port_to_ofp11(po->in_port); opo->actions_len = htons(len); @@ -6164,7 +6164,7 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg) } bad_len: - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %"PRIuSIZE" leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %"PRIu32" leftover " "bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -6483,7 +6483,7 @@ ofputil_decode_group_stats_reply(struct ofpbuf *msg, } if (!ogs11) { - VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIuSIZE" leftover bytes at end", + VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIu32" leftover bytes at end", ofpraw_get_name(raw), msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -6502,7 +6502,7 @@ ofputil_decode_group_stats_reply(struct ofpbuf *msg, gs->n_buckets = (length - base_len) / sizeof *obc; obc = ofpbuf_try_pull(msg, gs->n_buckets * sizeof *obc); if (!obc) { - VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIuSIZE" leftover bytes at end", + VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIu32" leftover bytes at end", ofpraw_get_name(raw), msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -6641,7 +6641,7 @@ ofputil_decode_group_desc_reply(struct ofputil_group_desc *gd, ogds = ofpbuf_try_pull(msg, sizeof *ogds); if (!ogds) { - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %"PRIuSIZE" " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %"PRIu32" " "leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -6972,7 +6972,7 @@ ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg) } bad_len: - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %"PRIuSIZE" leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %"PRIu32" leftover " "bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } diff --git a/lib/ofpbuf.c b/lib/ofpbuf.c index 9f22836ad..56e1ec6ca 100644 --- a/lib/ofpbuf.c +++ b/lib/ofpbuf.c @@ -30,9 +30,9 @@ ofpbuf_use__(struct ofpbuf *b, void *base, size_t allocated, b->allocated = allocated; b->source = source; b->size = 0; - b->l2 = b->l2_5 = b->l3 = b->l4 = NULL; + b->l2 = NULL; + b->l2_5_ofs = b->l3_ofs = b->l4_ofs = UINT16_MAX; list_poison(&b->list_node); - b->private_p = NULL; } /* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of @@ -164,24 +164,17 @@ struct ofpbuf * ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t headroom) { struct ofpbuf *new_buffer; - uintptr_t data_delta; new_buffer = ofpbuf_clone_data_with_headroom(buffer->data, buffer->size, headroom); - data_delta = (char *) new_buffer->data - (char *) buffer->data; - if (buffer->l2) { + uintptr_t data_delta = (char *)new_buffer->data - (char *)buffer->data; + new_buffer->l2 = (char *) buffer->l2 + data_delta; } - if (buffer->l2_5) { - new_buffer->l2_5 = (char *) buffer->l2_5 + data_delta; - } - if (buffer->l3) { - new_buffer->l3 = (char *) buffer->l3 + data_delta; - } - if (buffer->l4) { - new_buffer->l4 = (char *) buffer->l4 + data_delta; - } + new_buffer->l2_5_ofs = buffer->l2_5_ofs; + new_buffer->l3_ofs = buffer->l3_ofs; + new_buffer->l4_ofs = buffer->l4_ofs; return new_buffer; } @@ -263,19 +256,11 @@ ofpbuf_resize__(struct ofpbuf *b, size_t new_headroom, size_t new_tailroom) new_data = (char *) new_base + new_headroom; if (b->data != new_data) { uintptr_t data_delta = (char *) new_data - (char *) b->data; + b->data = new_data; if (b->l2) { b->l2 = (char *) b->l2 + data_delta; } - if (b->l2_5) { - b->l2_5 = (char *) b->l2_5 + data_delta; - } - if (b->l3) { - b->l3 = (char *) b->l3 + data_delta; - } - if (b->l4) { - b->l4 = (char *) b->l4 + data_delta; - } } } @@ -491,7 +476,7 @@ ofpbuf_to_string(const struct ofpbuf *b, size_t maxbytes) struct ds s; ds_init(&s); - ds_put_format(&s, "size=%"PRIuSIZE", allocated=%"PRIuSIZE", head=%"PRIuSIZE", tail=%"PRIuSIZE"\n", + ds_put_format(&s, "size=%"PRIu32", allocated=%"PRIu32", head=%"PRIuSIZE", tail=%"PRIuSIZE"\n", b->size, b->allocated, ofpbuf_headroom(b), ofpbuf_tailroom(b)); ds_put_hex_dump(&s, b->data, MIN(b->size, maxbytes), 0, false); @@ -510,3 +495,42 @@ ofpbuf_list_delete(struct list *list) ofpbuf_delete(b); } } + +static inline void +ofpbuf_adjust_layer_offset(uint16_t *offset, int increment) +{ + if (*offset != UINT16_MAX) { + *offset += increment; + } +} + +/* Adjust the size of the l2_5 portion of the ofpbuf, updating the l2 + * pointer and the layer offsets. The caller is responsible for + * modifying the contents. */ +void * +ofpbuf_resize_l2_5(struct ofpbuf *b, int increment) +{ + if (increment >= 0) { + ofpbuf_push_uninit(b, increment); + } else { + ofpbuf_pull(b, -increment); + } + + b->l2 = b->data; + /* Adjust layer offsets after l2_5. */ + ofpbuf_adjust_layer_offset(&b->l3_ofs, increment); + ofpbuf_adjust_layer_offset(&b->l4_ofs, increment); + + return b->l2; +} + +/* Adjust the size of the l2 portion of the ofpbuf, updating the l2 + * pointer and the layer offsets. The caller is responsible for + * modifying the contents. */ +void * +ofpbuf_resize_l2(struct ofpbuf *b, int increment) +{ + ofpbuf_resize_l2_5(b, increment); + ofpbuf_adjust_layer_offset(&b->l2_5_ofs, increment); + return b->l2; +} diff --git a/lib/ofpbuf.h b/lib/ofpbuf.h index bda514d89..8d1cb111e 100644 --- a/lib/ofpbuf.h +++ b/lib/ofpbuf.h @@ -27,7 +27,7 @@ extern "C" { #endif -enum ofpbuf_source { +enum OVS_PACKED_ENUM ofpbuf_source { OFPBUF_MALLOC, /* Obtained via malloc(). */ OFPBUF_STACK, /* Un-movable stack space or static buffer. */ OFPBUF_STUB, /* Starts on stack, may expand into heap. */ @@ -39,21 +39,35 @@ enum ofpbuf_source { * as necessary if it grows too large for the available memory. */ struct ofpbuf { void *base; /* First byte of allocated space. */ - size_t allocated; /* Number of bytes allocated. */ - enum ofpbuf_source source; /* Source of memory allocated as 'base'. */ - + uint32_t allocated; /* Number of bytes allocated. */ + uint32_t size; /* Number of bytes in use. */ void *data; /* First byte actually in use. */ - size_t size; /* Number of bytes in use. */ void *l2; /* Link-level header. */ - void *l2_5; /* MPLS label stack */ - void *l3; /* Network-level header. */ - void *l4; /* Transport-level header. */ - + uint16_t l2_5_ofs; /* MPLS label stack offset from l2, or + * UINT16_MAX */ + uint16_t l3_ofs; /* Network-level header offset from l2, or + * UINT16_MAX. */ + uint16_t l4_ofs; /* Transport-level header offset from l2, or + UINT16_MAX. */ + enum ofpbuf_source source; /* Source of memory allocated as 'base'. */ struct list list_node; /* Private list element for use by owner. */ - void *private_p; /* Private pointer for use by owner. */ }; +void * ofpbuf_resize_l2(struct ofpbuf *, int increment); +void * ofpbuf_resize_l2_5(struct ofpbuf *, int increment); +static inline void * ofpbuf_get_l2_5(const struct ofpbuf *); +static inline void ofpbuf_set_l2_5(struct ofpbuf *, void *); +static inline void * ofpbuf_get_l3(const struct ofpbuf *); +static inline void ofpbuf_set_l3(struct ofpbuf *, void *); +static inline void * ofpbuf_get_l4(const struct ofpbuf *); +static inline void ofpbuf_set_l4(struct ofpbuf *, void *); +static inline size_t ofpbuf_get_l4_size(const struct ofpbuf *); +static inline const void *ofpbuf_get_tcp_payload(const struct ofpbuf *); +static inline const void *ofpbuf_get_udp_payload(const struct ofpbuf *); +static inline const void *ofpbuf_get_sctp_payload(const struct ofpbuf *); +static inline const void *ofpbuf_get_icmp_payload(const struct ofpbuf *); + void ofpbuf_use(struct ofpbuf *, void *, size_t); void ofpbuf_use_stack(struct ofpbuf *, void *, size_t); void ofpbuf_use_stub(struct ofpbuf *, void *, size_t); @@ -212,9 +226,40 @@ static inline bool ofpbuf_equal(const struct ofpbuf *a, const struct ofpbuf *b) return a->size == b->size && memcmp(a->data, b->data, a->size) == 0; } +static inline void * ofpbuf_get_l2_5(const struct ofpbuf *b) +{ + return b->l2_5_ofs != UINT16_MAX ? (char *)b->l2 + b->l2_5_ofs : NULL; +} + +static inline void ofpbuf_set_l2_5(struct ofpbuf *b, void *l2_5) +{ + b->l2_5_ofs = l2_5 ? (char *)l2_5 - (char *)b->l2 : UINT16_MAX; +} + +static inline void * ofpbuf_get_l3(const struct ofpbuf *b) +{ + return b->l3_ofs != UINT16_MAX ? (char *)b->l2 + b->l3_ofs : NULL; +} + +static inline void ofpbuf_set_l3(struct ofpbuf *b, void *l3) +{ + b->l3_ofs = l3 ? (char *)l3 - (char *)b->l2 : UINT16_MAX; +} + +static inline void * ofpbuf_get_l4(const struct ofpbuf *b) +{ + return b->l4_ofs != UINT16_MAX ? (char *)b->l2 + b->l4_ofs : NULL; +} + +static inline void ofpbuf_set_l4(struct ofpbuf *b, void *l4) +{ + b->l4_ofs = l4 ? (char *)l4 - (char *)b->l2 : UINT16_MAX; +} + static inline size_t ofpbuf_get_l4_size(const struct ofpbuf *b) { - return b->l4 ? (const char *)ofpbuf_tail(b) - (const char *)b->l4 : 0; + return b->l4_ofs != UINT16_MAX + ? (const char *)ofpbuf_tail(b) - (const char *)ofpbuf_get_l4(b) : 0; } static inline const void *ofpbuf_get_tcp_payload(const struct ofpbuf *b) @@ -222,7 +267,7 @@ static inline const void *ofpbuf_get_tcp_payload(const struct ofpbuf *b) size_t l4_size = ofpbuf_get_l4_size(b); if (OVS_LIKELY(l4_size >= TCP_HEADER_LEN)) { - struct tcp_header *tcp = b->l4; + struct tcp_header *tcp = ofpbuf_get_l4(b); int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4; if (OVS_LIKELY(tcp_len >= TCP_HEADER_LEN && tcp_len <= l4_size)) { @@ -235,19 +280,19 @@ static inline const void *ofpbuf_get_tcp_payload(const struct ofpbuf *b) static inline const void *ofpbuf_get_udp_payload(const struct ofpbuf *b) { return OVS_LIKELY(ofpbuf_get_l4_size(b) >= UDP_HEADER_LEN) - ? (const char *)b->l4 + UDP_HEADER_LEN : NULL; + ? (const char *)ofpbuf_get_l4(b) + UDP_HEADER_LEN : NULL; } static inline const void *ofpbuf_get_sctp_payload(const struct ofpbuf *b) { return OVS_LIKELY(ofpbuf_get_l4_size(b) >= SCTP_HEADER_LEN) - ? (const char *)b->l4 + SCTP_HEADER_LEN : NULL; + ? (const char *)ofpbuf_get_l4(b) + SCTP_HEADER_LEN : NULL; } static inline const void *ofpbuf_get_icmp_payload(const struct ofpbuf *b) { return OVS_LIKELY(ofpbuf_get_l4_size(b) >= ICMP_HEADER_LEN) - ? (const char *)b->l4 + ICMP_HEADER_LEN : NULL; + ? (const char *)ofpbuf_get_l4(b) + ICMP_HEADER_LEN : NULL; } #ifdef __cplusplus diff --git a/lib/packets.c b/lib/packets.c index f8edb0205..3366089c1 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -173,25 +173,18 @@ compose_rarp(struct ofpbuf *b, const uint8_t eth_src[ETH_ADDR_LEN]) /* Insert VLAN header according to given TCI. Packet passed must be Ethernet * packet. Ignores the CFI bit of 'tci' using 0 instead. * - * Also sets 'packet->l2' to point to the new Ethernet header. */ + * Also sets 'packet->l2' to point to the new Ethernet header and adjusts + * the layer offsets accordingly. */ void eth_push_vlan(struct ofpbuf *packet, ovs_be16 tpid, ovs_be16 tci) { - struct eth_header *eh = packet->data; struct vlan_eth_header *veh; /* 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 = tpid; - tmp.veth_tci = tci & htons(~VLAN_CFI); - tmp.veth_next_type = eh->eth_type; - - veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN); - memcpy(veh, &tmp, sizeof tmp); - - packet->l2 = packet->data; + veh = ofpbuf_resize_l2(packet, VLAN_HEADER_LEN); + memmove(veh, (char *)veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN); + veh->veth_type = tpid; + veh->veth_tci = tci & htons(~VLAN_CFI); } /* Removes outermost VLAN header (if any is present) from 'packet'. @@ -202,17 +195,12 @@ void eth_pop_vlan(struct ofpbuf *packet) { struct vlan_eth_header *veh = packet->l2; + if (packet->size >= sizeof *veh && veh->veth_type == htons(ETH_TYPE_VLAN)) { - struct eth_header tmp; - memcpy(tmp.eth_dst, veh->veth_dst, ETH_ADDR_LEN); - memcpy(tmp.eth_src, veh->veth_src, ETH_ADDR_LEN); - tmp.eth_type = veh->veth_next_type; - - ofpbuf_pull(packet, VLAN_HEADER_LEN); - packet->l2 = (char*)packet->l2 + VLAN_HEADER_LEN; - memcpy(packet->data, &tmp, sizeof tmp); + memmove((char *)veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN); + ofpbuf_resize_l2(packet, -VLAN_HEADER_LEN); } } @@ -220,12 +208,14 @@ eth_pop_vlan(struct ofpbuf *packet) static void set_ethertype(struct ofpbuf *packet, ovs_be16 eth_type) { - struct eth_header *eh = packet->data; + struct eth_header *eh = packet->l2; if (eh->eth_type == htons(ETH_TYPE_VLAN)) { ovs_be16 *p; + char *l2_5 = ofpbuf_get_l2_5(packet); + p = ALIGNED_CAST(ovs_be16 *, - (char *)(packet->l2_5 ? packet->l2_5 : packet->l3) - 2); + (l2_5 ? l2_5 : (char *)ofpbuf_get_l3(packet)) - 2); *p = eth_type; } else { eh->eth_type = eth_type; @@ -234,7 +224,7 @@ set_ethertype(struct ofpbuf *packet, ovs_be16 eth_type) static bool is_mpls(struct ofpbuf *packet) { - return packet->l2_5 != NULL; + return packet->l2_5_ofs != UINT16_MAX; } /* Set time to live (TTL) of an MPLS label stack entry (LSE). */ @@ -283,34 +273,14 @@ set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos, ovs_be32 label) return lse; } -/* Push an new MPLS stack entry onto the MPLS stack and adjust 'packet->l2' and - * 'packet->l2_5' accordingly. The new entry will be the outermost entry on - * the stack. - * - * Previous to calling this function, 'packet->l2_5' must be set; if the MPLS - * label to be pushed will be the first label in 'packet', then it should be - * the same as 'packet->l3'. */ -static void -push_mpls_lse(struct ofpbuf *packet, struct mpls_hdr *mh) -{ - char * header; - size_t len; - header = ofpbuf_push_uninit(packet, MPLS_HLEN); - len = (char *)packet->l2_5 - (char *)packet->l2; - memmove(header, packet->l2, len); - memcpy(header + len, mh, sizeof *mh); - packet->l2 = (char*)packet->l2 - MPLS_HLEN; - packet->l2_5 = (char*)packet->l2_5 - MPLS_HLEN; -} - /* Set MPLS label stack entry to outermost MPLS header.*/ void set_mpls_lse(struct ofpbuf *packet, ovs_be32 mpls_lse) { - struct mpls_hdr *mh = packet->l2_5; - /* Packet type should be MPLS to set label stack entry. */ if (is_mpls(packet)) { + struct mpls_hdr *mh = ofpbuf_get_l2_5(packet); + /* Update mpls label stack entry. */ mh->mpls_lse = mpls_lse; } @@ -322,22 +292,25 @@ set_mpls_lse(struct ofpbuf *packet, ovs_be32 mpls_lse) void push_mpls(struct ofpbuf *packet, ovs_be16 ethtype, ovs_be32 lse) { - struct mpls_hdr mh; + char * header; + size_t len; if (!eth_type_mpls(ethtype)) { return; } - set_ethertype(packet, ethtype); - if (!is_mpls(packet)) { - /* Set MPLS label stack entry. */ - packet->l2_5 = packet->l3; + /* Set MPLS label stack offset. */ + packet->l2_5_ofs = packet->l3_ofs; } + set_ethertype(packet, ethtype); + /* Push new MPLS shim header onto packet. */ - mh.mpls_lse = lse; - push_mpls_lse(packet, &mh); + len = packet->l2_5_ofs; + header = ofpbuf_resize_l2_5(packet, MPLS_HLEN); + memmove(header, header + MPLS_HLEN, len); + memcpy(header + len, &lse, sizeof lse); } /* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry. @@ -347,23 +320,17 @@ push_mpls(struct ofpbuf *packet, ovs_be16 ethtype, ovs_be32 lse) void pop_mpls(struct ofpbuf *packet, ovs_be16 ethtype) { - struct mpls_hdr *mh = NULL; - if (is_mpls(packet)) { - size_t len; - mh = packet->l2_5; - len = (char*)packet->l2_5 - (char*)packet->l2; + struct mpls_hdr *mh = ofpbuf_get_l2_5(packet); + size_t len = packet->l2_5_ofs; + set_ethertype(packet, ethtype); if (mh->mpls_lse & htonl(MPLS_BOS_MASK)) { - packet->l2_5 = NULL; - } else { - packet->l2_5 = (char*)packet->l2_5 + MPLS_HLEN; + ofpbuf_set_l2_5(packet, NULL); } /* Shift the l2 header forward. */ memmove((char*)packet->data + MPLS_HLEN, packet->data, len); - packet->size -= MPLS_HLEN; - packet->data = (char*)packet->data + MPLS_HLEN; - packet->l2 = (char*)packet->l2 + MPLS_HLEN; + ofpbuf_resize_l2_5(packet, -MPLS_HLEN); } } @@ -578,7 +545,7 @@ 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. Sets 'b''s 'l2' and 'l3' pointers to the + * information by the caller. Sets 'b''s 'l2' pointer and 'l3' offset to the * Ethernet header and payload respectively. Aligns b->l3 on a 32-bit * boundary. * @@ -606,7 +573,7 @@ eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN], eth->eth_type = htons(eth_type); b->l2 = eth; - b->l3 = data; + ofpbuf_set_l3(b, data); return data; } @@ -615,16 +582,16 @@ static void packet_set_ipv4_addr(struct ofpbuf *packet, ovs_16aligned_be32 *addr, ovs_be32 new_addr) { - struct ip_header *nh = packet->l3; + struct ip_header *nh = ofpbuf_get_l3(packet); ovs_be32 old_addr = get_16aligned_be32(addr); size_t l4_size = ofpbuf_get_l4_size(packet); if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) { - struct tcp_header *th = packet->l4; + struct tcp_header *th = ofpbuf_get_l4(packet); th->tcp_csum = recalc_csum32(th->tcp_csum, old_addr, new_addr); } else if (nh->ip_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN ) { - struct udp_header *uh = packet->l4; + struct udp_header *uh = ofpbuf_get_l4(packet); if (uh->udp_csum) { uh->udp_csum = recalc_csum32(uh->udp_csum, old_addr, new_addr); @@ -640,7 +607,7 @@ packet_set_ipv4_addr(struct ofpbuf *packet, /* Returns true, if packet contains at least one routing header where * segements_left > 0. * - * This function assumes that L3 and L4 markers are set in the packet. */ + * This function assumes that L3 and L4 offsets are set in the packet. */ static bool packet_rh_present(struct ofpbuf *packet) { @@ -648,9 +615,9 @@ packet_rh_present(struct ofpbuf *packet) int nexthdr; size_t len; size_t remaining; - uint8_t *data = packet->l3; + uint8_t *data = ofpbuf_get_l3(packet); - remaining = (uint8_t *)packet->l4 - (uint8_t *)packet->l3; + remaining = packet->l4_ofs - packet->l3_ofs; if (remaining < sizeof *nh) { return false; @@ -729,11 +696,11 @@ packet_update_csum128(struct ofpbuf *packet, uint8_t proto, size_t l4_size = ofpbuf_get_l4_size(packet); if (proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) { - struct tcp_header *th = packet->l4; + struct tcp_header *th = ofpbuf_get_l4(packet); th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr); } else if (proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) { - struct udp_header *uh = packet->l4; + struct udp_header *uh = ofpbuf_get_l4(packet); if (uh->udp_csum) { uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr); @@ -779,7 +746,7 @@ void packet_set_ipv4(struct ofpbuf *packet, ovs_be32 src, ovs_be32 dst, uint8_t tos, uint8_t ttl) { - struct ip_header *nh = packet->l3; + struct ip_header *nh = ofpbuf_get_l3(packet); if (get_16aligned_be32(&nh->ip_src) != src) { packet_set_ipv4_addr(packet, &nh->ip_src, src); @@ -809,13 +776,13 @@ packet_set_ipv4(struct ofpbuf *packet, ovs_be32 src, ovs_be32 dst, /* Modifies the IPv6 header fields of 'packet' to be consistent with 'src', * 'dst', 'traffic class', and 'next hop'. Updates 'packet''s L4 checksums as * appropriate. 'packet' must contain a valid IPv6 packet with correctly - * populated l[347] markers. */ + * populated l[34] offsets. */ void packet_set_ipv6(struct ofpbuf *packet, uint8_t proto, const ovs_be32 src[4], const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl) { - struct ovs_16aligned_ip6_hdr *nh = packet->l3; + struct ovs_16aligned_ip6_hdr *nh = ofpbuf_get_l3(packet); if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) { packet_set_ipv6_addr(packet, proto, nh->ip6_src.be32, src, true); @@ -844,11 +811,11 @@ packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum) /* Sets the TCP source and destination port ('src' and 'dst' respectively) of * the TCP header contained in 'packet'. 'packet' must be a valid TCP packet - * with its l4 marker properly populated. */ + * with its l4 offset properly populated. */ void packet_set_tcp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst) { - struct tcp_header *th = packet->l4; + struct tcp_header *th = ofpbuf_get_l4(packet); packet_set_port(&th->tcp_src, src, &th->tcp_csum); packet_set_port(&th->tcp_dst, dst, &th->tcp_csum); @@ -856,11 +823,11 @@ packet_set_tcp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst) /* Sets the UDP source and destination port ('src' and 'dst' respectively) of * the UDP header contained in 'packet'. 'packet' must be a valid UDP packet - * with its l4 marker properly populated. */ + * with its l4 offset properly populated. */ void packet_set_udp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst) { - struct udp_header *uh = packet->l4; + struct udp_header *uh = ofpbuf_get_l4(packet); if (uh->udp_csum) { packet_set_port(&uh->udp_src, src, &uh->udp_csum); @@ -877,22 +844,22 @@ packet_set_udp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst) /* Sets the SCTP source and destination port ('src' and 'dst' respectively) of * the SCTP header contained in 'packet'. 'packet' must be a valid SCTP packet - * with its l4 marker properly populated. */ + * with its l4 offset properly populated. */ void packet_set_sctp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst) { - struct sctp_header *sh = packet->l4; + struct sctp_header *sh = ofpbuf_get_l4(packet); ovs_be32 old_csum, old_correct_csum, new_csum; uint16_t tp_len = packet->size - ((uint8_t*)sh - (uint8_t*)packet->data); old_csum = sh->sctp_csum; sh->sctp_csum = 0; - old_correct_csum = crc32c(packet->l4, tp_len); + old_correct_csum = crc32c((void *)sh, tp_len); sh->sctp_src = src; sh->sctp_dst = dst; - new_csum = crc32c(packet->l4, tp_len); + new_csum = crc32c((void *)sh, tp_len); sh->sctp_csum = old_csum ^ old_correct_csum ^ new_csum; } diff --git a/lib/pcap-file.c b/lib/pcap-file.c index b449eff8b..a92e7d3c4 100644 --- a/lib/pcap-file.c +++ b/lib/pcap-file.c @@ -310,7 +310,7 @@ tcp_reader_run(struct tcp_reader *r, const struct flow *flow, || !l7) { return NULL; } - tcp = packet->l4; + tcp = ofpbuf_get_l4(packet); flags = TCP_FLAGS(tcp->tcp_ctl); l7_length = (char *) ofpbuf_tail(packet) - l7; seq = ntohl(get_16aligned_be32(&tcp->tcp_seq)); diff --git a/lib/rconn.c b/lib/rconn.c index 72688ba8d..a5368d563 100644 --- a/lib/rconn.c +++ b/lib/rconn.c @@ -716,10 +716,15 @@ rconn_send__(struct rconn *rc, struct ofpbuf *b, if (rconn_is_connected(rc)) { COVERAGE_INC(rconn_queued); copy_to_monitor(rc, b); - b->private_p = counter; + if (counter) { rconn_packet_counter_inc(counter, b->size); } + + /* Use 'l2' as a private pointer while 'b' is in txq. */ + ovs_assert(b->l2 == b->data); + b->l2 = counter; + list_push_back(&rc->txq, &b->list_node); /* If the queue was empty before we added 'b', try to send some @@ -1103,16 +1108,18 @@ try_send(struct rconn *rc) { struct ofpbuf *msg = ofpbuf_from_list(rc->txq.next); unsigned int n_bytes = msg->size; - struct rconn_packet_counter *counter = msg->private_p; + struct rconn_packet_counter *counter = msg->l2; int retval; /* Eagerly remove 'msg' from the txq. We can't remove it from the list * after sending, if sending is successful, because it is then owned by the * vconn, which might have freed it already. */ list_remove(&msg->list_node); + msg->l2 = msg->data; /* Restore 'l2'. */ retval = vconn_send(rc->vconn, msg); if (retval) { + msg->l2 = counter; /* 'l2' is a private pointer while msg is in txq. */ list_push_front(&rc->txq, &msg->list_node); if (retval != EAGAIN) { report_error(rc, retval); @@ -1205,7 +1212,7 @@ flush_queue(struct rconn *rc) } while (!list_is_empty(&rc->txq)) { struct ofpbuf *b = ofpbuf_from_list(list_pop_front(&rc->txq)); - struct rconn_packet_counter *counter = b->private_p; + struct rconn_packet_counter *counter = b->l2; if (counter) { rconn_packet_counter_dec(counter, b->size); } diff --git a/lib/stp.c b/lib/stp.c index c5aec57d2..78dacb388 100644 --- a/lib/stp.c +++ b/lib/stp.c @@ -1537,7 +1537,7 @@ stp_send_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) pkt = ofpbuf_new(ETH_HEADER_LEN + LLC_HEADER_LEN + bpdu_size); pkt->l2 = eth = ofpbuf_put_zeros(pkt, sizeof *eth); llc = ofpbuf_put_zeros(pkt, sizeof *llc); - pkt->l3 = ofpbuf_put(pkt, bpdu, bpdu_size); + ofpbuf_set_l3(pkt, ofpbuf_put(pkt, bpdu, bpdu_size)); /* 802.2 header. */ memcpy(eth->eth_dst, eth_addr_stp, ETH_ADDR_LEN); diff --git a/lib/util.h b/lib/util.h index 13ff58ece..1bbcee27b 100644 --- a/lib/util.h +++ b/lib/util.h @@ -17,6 +17,7 @@ #ifndef UTIL_H #define UTIL_H 1 +#include #include #include #include diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 87a61f7e3..7172cb216 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -2419,7 +2419,9 @@ bundle_send_learning_packets(struct ofbundle *bundle) learning_packet = bond_compose_learning_packet(bundle->bond, e->mac, e->vlan, &port_void); - learning_packet->private_p = port_void; + /* Temporarily use l2 as a private pointer (see below). */ + ovs_assert(learning_packet->l2 == learning_packet->data); + learning_packet->l2 = port_void; list_push_back(&packets, &learning_packet->list_node); } } @@ -2428,8 +2430,11 @@ bundle_send_learning_packets(struct ofbundle *bundle) error = n_packets = n_errors = 0; LIST_FOR_EACH (learning_packet, list_node, &packets) { int ret; + void *port_void = learning_packet->l2; - ret = ofproto_dpif_send_packet(learning_packet->private_p, learning_packet); + /* Restore l2. */ + learning_packet->l2 = learning_packet->data; + ret = ofproto_dpif_send_packet(port_void, learning_packet); if (ret) { error = ret; n_errors++; diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 8c11aff82..a7bf4df4f 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1299,8 +1299,8 @@ struct ofproto_class { * information in 'flow' is extracted from 'packet', except for * flow->tunnel and flow->in_port, which are assigned the correct values * for the incoming packet. The register values are zeroed. 'packet''s - * header pointers (e.g. packet->l3) are appropriately initialized. - * packet->l3 is aligned on a 32-bit boundary. + * header pointers and offsets (e.g. packet->l3) are appropriately + * initialized. packet->l3 is aligned on a 32-bit boundary. * * The implementation should add the statistics for 'packet' into 'rule'. * diff --git a/tests/test-netflow.c b/tests/test-netflow.c index b6c3109d0..392c6ec76 100644 --- a/tests/test-netflow.c +++ b/tests/test-netflow.c @@ -162,7 +162,7 @@ print_netflow(struct ofpbuf *buf) } if (buf->size) { - printf("%"PRIuSIZE" extra bytes after last record\n", buf->size); + printf("%"PRIu32" extra bytes after last record\n", buf->size); } } diff --git a/tests/test-odp.c b/tests/test-odp.c index a27bf7f7b..d41db8480 100644 --- a/tests/test-odp.c +++ b/tests/test-odp.c @@ -78,7 +78,7 @@ parse_keys(bool wc_keys) odp_flow_key_from_flow(&odp_key, &flow, flow.in_port.odp_port); if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) { - printf ("too long: %"PRIuSIZE" > %d\n", + printf ("too long: %"PRIu32" > %d\n", odp_key.size, ODPUTIL_FLOW_KEY_BYTES); exit_code = 1; } diff --git a/tests/test-stp.c b/tests/test-stp.c index be1b3959f..9d17745c8 100644 --- a/tests/test-stp.c +++ b/tests/test-stp.c @@ -92,7 +92,7 @@ send_bpdu(struct ofpbuf *pkt, int port_no, void *b_) assert(port_no < b->n_ports); lan = b->ports[port_no]; if (lan) { - const void *data = pkt->l3; + const void *data = ofpbuf_get_l3(pkt); size_t size = (char *) ofpbuf_tail(pkt) - (char *) data; int i; diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index bd3d5a684..12942471e 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -1963,13 +1963,13 @@ ofctl_ping(int argc, char *argv[]) if (ofptype_pull(&type, reply) || type != OFPTYPE_ECHO_REPLY || reply->size != payload - || memcmp(request->l3, reply->l3, payload)) { + || memcmp(ofpbuf_get_l3(request), ofpbuf_get_l3(reply), payload)) { printf("Reply does not match request. Request:\n"); ofp_print(stdout, request, request->size, verbosity + 2); printf("Reply:\n"); ofp_print(stdout, reply, reply->size, verbosity + 2); } - printf("%"PRIuSIZE" bytes from %s: xid=%08"PRIx32" time=%.1f ms\n", + printf("%"PRIu32" bytes from %s: xid=%08"PRIx32" time=%.1f ms\n", reply->size, argv[1], ntohl(rpy_hdr->xid), (1000*(double)(end.tv_sec - start.tv_sec)) + (.001*(end.tv_usec - start.tv_usec))); @@ -2981,7 +2981,7 @@ ofctl_parse_ofp10_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ovs_fatal(0, "Trailing garbage in hex data"); } if (match_expout.size != sizeof(struct ofp10_match)) { - ovs_fatal(0, "Input is %"PRIuSIZE" bytes, expected %"PRIuSIZE, + ovs_fatal(0, "Input is %"PRIu32" bytes, expected %"PRIuSIZE, match_expout.size, sizeof(struct ofp10_match)); } @@ -2996,7 +2996,7 @@ ofctl_parse_ofp10_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ovs_fatal(0, "Trailing garbage in hex data"); } if (match_in.size != sizeof(struct ofp10_match)) { - ovs_fatal(0, "Input is %"PRIuSIZE" bytes, expected %"PRIuSIZE, + ovs_fatal(0, "Input is %"PRIu32" bytes, expected %"PRIuSIZE, match_in.size, sizeof(struct ofp10_match)); } @@ -3045,7 +3045,7 @@ ofctl_parse_ofp11_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ovs_fatal(0, "Trailing garbage in hex data"); } if (match_in.size != sizeof(struct ofp11_match)) { - ovs_fatal(0, "Input is %"PRIuSIZE" bytes, expected %"PRIuSIZE, + ovs_fatal(0, "Input is %"PRIu32" bytes, expected %"PRIuSIZE, match_in.size, sizeof(struct ofp11_match)); }