aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/flow.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch/flow.c')
-rw-r--r--net/openvswitch/flow.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 98c70630ad06..c3294cebc4f2 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -604,6 +604,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
604 604
605 key->phy.priority = skb->priority; 605 key->phy.priority = skb->priority;
606 key->phy.in_port = in_port; 606 key->phy.in_port = in_port;
607 key->phy.skb_mark = skb->mark;
607 608
608 skb_reset_mac_header(skb); 609 skb_reset_mac_header(skb);
609 610
@@ -689,7 +690,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
689 } 690 }
690 } 691 }
691 692
692 } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) { 693 } else if ((key->eth.type == htons(ETH_P_ARP) ||
694 key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) {
693 struct arp_eth_header *arp; 695 struct arp_eth_header *arp;
694 696
695 arp = (struct arp_eth_header *)skb_network_header(skb); 697 arp = (struct arp_eth_header *)skb_network_header(skb);
@@ -702,15 +704,11 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
702 /* We only match on the lower 8 bits of the opcode. */ 704 /* We only match on the lower 8 bits of the opcode. */
703 if (ntohs(arp->ar_op) <= 0xff) 705 if (ntohs(arp->ar_op) <= 0xff)
704 key->ip.proto = ntohs(arp->ar_op); 706 key->ip.proto = ntohs(arp->ar_op);
705 707 memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
706 if (key->ip.proto == ARPOP_REQUEST 708 memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
707 || key->ip.proto == ARPOP_REPLY) { 709 memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
708 memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src)); 710 memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
709 memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst)); 711 key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
710 memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
711 memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
712 key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
713 }
714 } 712 }
715 } else if (key->eth.type == htons(ETH_P_IPV6)) { 713 } else if (key->eth.type == htons(ETH_P_IPV6)) {
716 int nh_len; /* IPv6 Header + Extensions */ 714 int nh_len; /* IPv6 Header + Extensions */
@@ -806,6 +804,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
806 [OVS_KEY_ATTR_ENCAP] = -1, 804 [OVS_KEY_ATTR_ENCAP] = -1,
807 [OVS_KEY_ATTR_PRIORITY] = sizeof(u32), 805 [OVS_KEY_ATTR_PRIORITY] = sizeof(u32),
808 [OVS_KEY_ATTR_IN_PORT] = sizeof(u32), 806 [OVS_KEY_ATTR_IN_PORT] = sizeof(u32),
807 [OVS_KEY_ATTR_SKB_MARK] = sizeof(u32),
809 [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet), 808 [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet),
810 [OVS_KEY_ATTR_VLAN] = sizeof(__be16), 809 [OVS_KEY_ATTR_VLAN] = sizeof(__be16),
811 [OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16), 810 [OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16),
@@ -991,6 +990,10 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
991 } else { 990 } else {
992 swkey->phy.in_port = DP_MAX_PORTS; 991 swkey->phy.in_port = DP_MAX_PORTS;
993 } 992 }
993 if (attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
994 swkey->phy.skb_mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
995 attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
996 }
994 997
995 /* Data attributes. */ 998 /* Data attributes. */
996 if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET))) 999 if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET)))
@@ -1090,7 +1093,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
1090 if (err) 1093 if (err)
1091 return err; 1094 return err;
1092 } 1095 }
1093 } else if (swkey->eth.type == htons(ETH_P_ARP)) { 1096 } else if (swkey->eth.type == htons(ETH_P_ARP) ||
1097 swkey->eth.type == htons(ETH_P_RARP)) {
1094 const struct ovs_key_arp *arp_key; 1098 const struct ovs_key_arp *arp_key;
1095 1099
1096 if (!(attrs & (1 << OVS_KEY_ATTR_ARP))) 1100 if (!(attrs & (1 << OVS_KEY_ATTR_ARP)))
@@ -1117,6 +1121,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
1117 1121
1118/** 1122/**
1119 * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key. 1123 * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key.
1124 * @priority: receives the skb priority
1125 * @mark: receives the skb mark
1120 * @in_port: receives the extracted input port. 1126 * @in_port: receives the extracted input port.
1121 * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute 1127 * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
1122 * sequence. 1128 * sequence.
@@ -1126,7 +1132,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
1126 * get the metadata, that is, the parts of the flow key that cannot be 1132 * get the metadata, that is, the parts of the flow key that cannot be
1127 * extracted from the packet itself. 1133 * extracted from the packet itself.
1128 */ 1134 */
1129int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, 1135int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port,
1130 const struct nlattr *attr) 1136 const struct nlattr *attr)
1131{ 1137{
1132 const struct nlattr *nla; 1138 const struct nlattr *nla;
@@ -1134,6 +1140,7 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
1134 1140
1135 *in_port = DP_MAX_PORTS; 1141 *in_port = DP_MAX_PORTS;
1136 *priority = 0; 1142 *priority = 0;
1143 *mark = 0;
1137 1144
1138 nla_for_each_nested(nla, attr, rem) { 1145 nla_for_each_nested(nla, attr, rem) {
1139 int type = nla_type(nla); 1146 int type = nla_type(nla);
@@ -1152,6 +1159,10 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
1152 return -EINVAL; 1159 return -EINVAL;
1153 *in_port = nla_get_u32(nla); 1160 *in_port = nla_get_u32(nla);
1154 break; 1161 break;
1162
1163 case OVS_KEY_ATTR_SKB_MARK:
1164 *mark = nla_get_u32(nla);
1165 break;
1155 } 1166 }
1156 } 1167 }
1157 } 1168 }
@@ -1173,6 +1184,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
1173 nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port)) 1184 nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port))
1174 goto nla_put_failure; 1185 goto nla_put_failure;
1175 1186
1187 if (swkey->phy.skb_mark &&
1188 nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, swkey->phy.skb_mark))
1189 goto nla_put_failure;
1190
1176 nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key)); 1191 nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
1177 if (!nla) 1192 if (!nla)
1178 goto nla_put_failure; 1193 goto nla_put_failure;
@@ -1226,7 +1241,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
1226 ipv6_key->ipv6_tclass = swkey->ip.tos; 1241 ipv6_key->ipv6_tclass = swkey->ip.tos;
1227 ipv6_key->ipv6_hlimit = swkey->ip.ttl; 1242 ipv6_key->ipv6_hlimit = swkey->ip.ttl;
1228 ipv6_key->ipv6_frag = swkey->ip.frag; 1243 ipv6_key->ipv6_frag = swkey->ip.frag;
1229 } else if (swkey->eth.type == htons(ETH_P_ARP)) { 1244 } else if (swkey->eth.type == htons(ETH_P_ARP) ||
1245 swkey->eth.type == htons(ETH_P_RARP)) {
1230 struct ovs_key_arp *arp_key; 1246 struct ovs_key_arp *arp_key;
1231 1247
1232 nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key)); 1248 nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));