/* We only process the first fragment. */
if (frag_hdr->ip6f_offlg != htons(0)) {
- if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) == htons(0)) {
- flow->nw_frag = FLOW_NW_FRAG_ANY;
- } else {
+ flow->nw_frag = FLOW_NW_FRAG_ANY;
+ if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) != htons(0)) {
flow->nw_frag |= FLOW_NW_FRAG_LATER;
nexthdr = IPPROTO_FRAGMENT;
break;
* present and has a correct length, and otherwise NULL.
*/
void
-flow_extract(struct ofpbuf *packet, uint32_t skb_priority,
+flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark,
const struct flow_tnl *tnl, uint16_t ofp_in_port,
struct flow *flow)
{
}
flow->in_port = ofp_in_port;
flow->skb_priority = skb_priority;
+ flow->skb_mark = skb_mark;
packet->l2 = b.data;
packet->l3 = NULL;
if (nh) {
packet->l4 = b.data;
- flow->nw_src = get_unaligned_be32(&nh->ip_src);
- flow->nw_dst = get_unaligned_be32(&nh->ip_dst);
+ flow->nw_src = get_16aligned_be32(&nh->ip_src);
+ flow->nw_dst = get_16aligned_be32(&nh->ip_dst);
flow->nw_proto = nh->ip_proto;
flow->nw_tos = nh->ip_tos;
packet->l7 = b.data;
}
}
- } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
+ } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
+ flow->dl_type == htons(ETH_TYPE_RARP)) {
const struct arp_eth_header *arp = pull_arp(&b);
if (arp && arp->ar_hrd == htons(1)
&& arp->ar_pro == htons(ETH_TYPE_IP)
flow->nw_proto = ntohs(arp->ar_op);
}
- flow->nw_src = arp->ar_spa;
- flow->nw_dst = arp->ar_tpa;
+ flow->nw_src = get_16aligned_be32(&arp->ar_spa);
+ flow->nw_dst = get_16aligned_be32(&arp->ar_tpa);
memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
}
void
flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
fmd->tun_id = flow->tunnel.tun_id;
fmd->metadata = flow->metadata;
return ds_cstr(&ds);
}
+const char *
+flow_tun_flag_to_string(uint32_t flags)
+{
+ switch (flags) {
+ case FLOW_TNL_F_DONT_FRAGMENT:
+ return "df";
+ case FLOW_TNL_F_CSUM:
+ return "csum";
+ case FLOW_TNL_F_KEY:
+ return "key";
+ default:
+ return NULL;
+ }
+}
+
+void
+format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t),
+ uint32_t flags, char del)
+{
+ uint32_t bad = 0;
+
+ if (!flags) {
+ return;
+ }
+ while (flags) {
+ uint32_t bit = rightmost_1bit(flags);
+ const char *s;
+
+ s = bit_to_string(bit);
+ if (s) {
+ ds_put_format(ds, "%s%c", s, del);
+ } else {
+ bad |= bit;
+ }
+
+ flags &= ~bit;
+ }
+
+ if (bad) {
+ ds_put_format(ds, "0x%"PRIx32"%c", bad, del);
+ }
+ ds_chomp(ds, del);
+}
+
void
flow_format(struct ds *ds, const struct flow *flow)
{
struct match match;
match_wc_init(&match, flow);
- match_format(&match, ds, flow->skb_priority);
+ match_format(&match, ds, OFP_DEFAULT_PRIORITY);
}
void
ip->ip_ihl_ver = IP_IHL_VER(5, 4);
ip->ip_tos = flow->nw_tos;
ip->ip_proto = flow->nw_proto;
- ip->ip_src = flow->nw_src;
- ip->ip_dst = flow->nw_dst;
+ put_16aligned_be32(&ip->ip_src, flow->nw_src);
+ put_16aligned_be32(&ip->ip_dst, flow->nw_dst);
if (flow->nw_frag & FLOW_NW_FRAG_ANY) {
ip->ip_frag_off |= htons(IP_MORE_FRAGMENTS);
ip->ip_csum = csum(ip, sizeof *ip);
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
/* XXX */
- } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
+ } 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);
if (flow->nw_proto == ARP_OP_REQUEST ||
flow->nw_proto == ARP_OP_REPLY) {
- arp->ar_spa = flow->nw_src;
- arp->ar_tpa = flow->nw_dst;
+ put_16aligned_be32(&arp->ar_spa, flow->nw_src);
+ put_16aligned_be32(&arp->ar_tpa, flow->nw_dst);
memcpy(arp->ar_sha, flow->arp_sha, ETH_ADDR_LEN);
memcpy(arp->ar_tha, flow->arp_tha, ETH_ADDR_LEN);
}