return ofpbuf_try_pull(packet, UDP_HEADER_LEN);
}
+static struct sctp_header *
+pull_sctp(struct ofpbuf *packet)
+{
+ return ofpbuf_try_pull(packet, SCTP_HEADER_LEN);
+}
+
static struct icmp_header *
pull_icmp(struct ofpbuf *packet)
{
}
}
+static void
+parse_sctp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow)
+{
+ const struct sctp_header *sctp = pull_sctp(b);
+ if (sctp) {
+ flow->tp_src = sctp->sctp_src;
+ flow->tp_dst = sctp->sctp_dst;
+ packet->l7 = b->data;
+ }
+}
+
static bool
parse_icmpv6(struct ofpbuf *b, struct flow *flow)
{
* - packet->l4 to just past the IPv4 header, if one is present and has a
* correct length, and otherwise NULL.
*
- * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
+ * - packet->l7 to just past the TCP/UDP/SCTP/ICMP header, if one is
* present and has a correct length, and otherwise NULL.
*/
void
-flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark,
+flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t pkt_mark,
const struct flow_tnl *tnl, const union flow_in_port *in_port,
struct flow *flow)
{
flow->in_port = *in_port;
}
flow->skb_priority = skb_priority;
- flow->skb_mark = skb_mark;
+ flow->pkt_mark = pkt_mark;
packet->l2 = b.data;
packet->l2_5 = NULL;
parse_tcp(packet, &b, flow);
} else if (flow->nw_proto == IPPROTO_UDP) {
parse_udp(packet, &b, flow);
+ } else if (flow->nw_proto == IPPROTO_SCTP) {
+ parse_sctp(packet, &b, flow);
} else if (flow->nw_proto == IPPROTO_ICMP) {
const struct icmp_header *icmp = pull_icmp(&b);
if (icmp) {
parse_tcp(packet, &b, flow);
} else if (flow->nw_proto == IPPROTO_UDP) {
parse_udp(packet, &b, flow);
+ } else if (flow->nw_proto == IPPROTO_SCTP) {
+ parse_sctp(packet, &b, flow);
} else if (flow->nw_proto == IPPROTO_ICMPV6) {
if (parse_icmpv6(&b, flow)) {
packet->l7 = b.data;
fmd->tun_dst = flow->tunnel.ip_dst;
fmd->metadata = flow->metadata;
memcpy(fmd->regs, flow->regs, sizeof fmd->regs);
+ fmd->pkt_mark = flow->pkt_mark;
fmd->in_port = flow->in_port.ofp_port;
}
if (fields.eth_type == htons(ETH_TYPE_IP)) {
fields.ipv4_addr = flow->nw_src ^ flow->nw_dst;
fields.ip_proto = flow->nw_proto;
- if (fields.ip_proto == IPPROTO_TCP) {
+ if (fields.ip_proto == IPPROTO_TCP || fields.ip_proto == IPPROTO_SCTP) {
fields.tp_port = flow->tp_src ^ flow->tp_dst;
}
} else if (fields.eth_type == htons(ETH_TYPE_IPV6)) {
ipv6_addr[i] = a[i] ^ b[i];
}
fields.ip_proto = flow->nw_proto;
- if (fields.ip_proto == IPPROTO_TCP) {
+ if (fields.ip_proto == IPPROTO_TCP || fields.ip_proto == IPPROTO_SCTP) {
fields.tp_port = flow->tp_src ^ flow->tp_dst;
}
}
if (flow->dl_type == htons(ETH_TYPE_IP)) {
memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
- } else {
+ } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
}
b->l4 = udp = ofpbuf_put_zeros(b, sizeof *udp);
udp->udp_src = flow->tp_src;
udp->udp_dst = flow->tp_dst;
+ } else if (flow->nw_proto == IPPROTO_SCTP) {
+ struct sctp_header *sctp;
+
+ b->l4 = sctp = ofpbuf_put_zeros(b, sizeof *sctp);
+ sctp->sctp_src = flow->tp_src;
+ sctp->sctp_dst = flow->tp_dst;
} else if (flow->nw_proto == IPPROTO_ICMP) {
struct icmp_header *icmp;