@@ -16,6 +16,8 @@
*/
#include <config.h>
+#include <sys/types.h>
+#include <netinet/ip6.h>
#include <rte_flow.h>
#include "cmap.h"
@@ -26,6 +28,8 @@
#include "openvswitch/vlog.h"
#include "packets.h"
#include "uuid.h"
+#include "id-pool.h"
+#include "odp-util.h"
VLOG_DEFINE_THIS_MODULE(netdev_offload_dpdk);
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(100, 5);
@@ -970,6 +974,140 @@ parse_set_actions(struct flow_actions *actions,
return 0;
}
+/* Maximum number of items in struct rte_flow_action_vxlan_encap.
+ * ETH / IPv4(6) / UDP / VXLAN / END
+ */
+#define ACTION_VXLAN_ENCAP_ITEMS_NUM 5
+
+static int
+add_vxlan_encap_action(struct flow_actions *actions,
+ const void *header)
+{
+ const struct eth_header *eth;
+ const struct udp_header *udp;
+ struct vxlan_data {
+ struct rte_flow_action_vxlan_encap conf;
+ struct rte_flow_item items[0];
+ } *vxlan_data;
+ BUILD_ASSERT_DECL(offsetof(struct vxlan_data, conf) == 0);
+ const void *vxlan;
+ const void *l3;
+ const void *l4;
+ int field;
+
+ VLOG_DBG_RL(&rl, "TIMO DBG: in add_vxlan_encap_action");
+ vxlan_data = xzalloc(sizeof *vxlan_data +
+ sizeof(struct rte_flow_item) *
+ ACTION_VXLAN_ENCAP_ITEMS_NUM);
+ field = 0;
+
+ eth = header;
+ /* Ethernet */
+ vxlan_data->items[field].type = RTE_FLOW_ITEM_TYPE_ETH;
+ vxlan_data->items[field].spec = eth;
+ vxlan_data->items[field].mask = &rte_flow_item_eth_mask;
+ field++;
+
+ l3 = eth + 1;
+ /* IP */
+ if (eth->eth_type == htons(ETH_TYPE_IP)) {
+ /* IPv4 */
+ const struct ip_header *ip = l3;
+
+ vxlan_data->items[field].type = RTE_FLOW_ITEM_TYPE_IPV4;
+ vxlan_data->items[field].spec = ip;
+ vxlan_data->items[field].mask = &rte_flow_item_ipv4_mask;
+
+ if (ip->ip_proto != IPPROTO_UDP) {
+ goto err;
+ }
+ l4 = (ip + 1);
+ } else if (eth->eth_type == htons(ETH_TYPE_IPV6)) {
+ const struct ovs_16aligned_ip6_hdr *ip6 = l3;
+
+ vxlan_data->items[field].type = RTE_FLOW_ITEM_TYPE_IPV6;
+ vxlan_data->items[field].spec = ip6;
+ vxlan_data->items[field].mask = &rte_flow_item_ipv6_mask;
+
+ if (ip6->ip6_nxt != IPPROTO_UDP) {
+ goto err;
+ }
+ l4 = (ip6 + 1);
+ } else {
+ goto err;
+ }
+ field++;
+
+ udp = (const struct udp_header *)l4;
+ vxlan_data->items[field].type = RTE_FLOW_ITEM_TYPE_UDP;
+ vxlan_data->items[field].spec = udp;
+ vxlan_data->items[field].mask = &rte_flow_item_udp_mask;
+ field++;
+
+ vxlan = (udp + 1);
+ vxlan_data->items[field].type = RTE_FLOW_ITEM_TYPE_VXLAN;
+ vxlan_data->items[field].spec = vxlan;
+ vxlan_data->items[field].mask = &rte_flow_item_vxlan_mask;
+ field++;
+
+ vxlan_data->items[field].type = RTE_FLOW_ITEM_TYPE_END;
+
+ vxlan_data->conf.definition = vxlan_data->items;
+
+ add_flow_action(actions, RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, vxlan_data);
+
+ return 0;
+err:
+ free(vxlan_data);
+ return -1;
+}
+
+static int
+parse_clone_actions(struct netdev *netdev,
+ struct flow_actions *actions,
+ const struct nlattr *clone_actions,
+ const size_t clone_actions_len,
+ struct offload_info *info)
+{
+ const struct nlattr *ca;
+ unsigned int cleft;
+
+ NL_ATTR_FOR_EACH_UNSAFE (ca, cleft, clone_actions, clone_actions_len) {
+ int clone_type = nl_attr_type(ca);
+
+ VLOG_DBG_RL(&rl, "TIMO DBG: in parse_clone_action");
+
+ if (clone_type == OVS_ACTION_ATTR_TUNNEL_PUSH) {
+ const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca);
+ struct rte_flow_action_raw_encap *raw_encap;
+
+ if (tnl_push->tnl_type == OVS_VPORT_TYPE_VXLAN &&
+ !add_vxlan_encap_action(actions, tnl_push->header)) {
+ continue;
+ }
+
+ raw_encap = xzalloc(sizeof *raw_encap);
+ raw_encap->data = (uint8_t *)tnl_push->header;
+ raw_encap->preserve = NULL;
+ raw_encap->size = tnl_push->header_len;
+
+ add_flow_action(actions, RTE_FLOW_ACTION_TYPE_RAW_ENCAP,
+ raw_encap);
+ } else if (clone_type == OVS_ACTION_ATTR_OUTPUT) {
+ if (add_output_action(netdev, actions, ca,info)) {
+ return -1;
+ }
+ } else {
+ VLOG_DBG_RL(&rl,
+ "Unsupported nested action inside clone(), "
+ "action type: %d", clone_type);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static int
parse_flow_actions(struct netdev *netdev,
struct flow_actions *actions,
@@ -998,6 +1136,15 @@ parse_flow_actions(struct netdev *netdev,
masked)) {
return -1;
}
+ } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE) {
+ const struct nlattr *clone_actions = nl_attr_get(nla);
+ size_t clone_actions_len = nl_attr_get_size(nla);
+
+ if (parse_clone_actions(netdev, actions, clone_actions,
+ clone_actions_len,info)) {
+ return -1;
+ }
+
} else {
VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla));
return -1;
From: Liuchang <liuchang@cmss.chinamobile.com> Code Source From: Self Code Description: Translate VxLAN encap action(For DPDK, it's clone(tnl_push) action) into RTE_FLOW_ACTION_TYPE_RAW_ENCAP Jira: #[Optional] 市场项目编号(名称):[Optional] --- lib/netdev-offload-dpdk.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+)