diff options
-rw-r--r-- | include/uapi/linux/openvswitch.h | 4 | ||||
-rw-r--r-- | net/openvswitch/datapath.c | 14 | ||||
-rw-r--r-- | net/openvswitch/datapath.h | 2 |
3 files changed, 20 insertions, 0 deletions
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index d120f9fe0017..07ef2c3e21fa 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h | |||
@@ -75,6 +75,7 @@ enum ovs_datapath_attr { | |||
75 | OVS_DP_ATTR_UPCALL_PID, /* Netlink PID to receive upcalls */ | 75 | OVS_DP_ATTR_UPCALL_PID, /* Netlink PID to receive upcalls */ |
76 | OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */ | 76 | OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */ |
77 | OVS_DP_ATTR_MEGAFLOW_STATS, /* struct ovs_dp_megaflow_stats */ | 77 | OVS_DP_ATTR_MEGAFLOW_STATS, /* struct ovs_dp_megaflow_stats */ |
78 | OVS_DP_ATTR_USER_FEATURES, /* OVS_DP_F_* */ | ||
78 | __OVS_DP_ATTR_MAX | 79 | __OVS_DP_ATTR_MAX |
79 | }; | 80 | }; |
80 | 81 | ||
@@ -106,6 +107,9 @@ struct ovs_vport_stats { | |||
106 | __u64 tx_dropped; /* no space available in linux */ | 107 | __u64 tx_dropped; /* no space available in linux */ |
107 | }; | 108 | }; |
108 | 109 | ||
110 | /* Allow last Netlink attribute to be unaligned */ | ||
111 | #define OVS_DP_F_UNALIGNED (1 << 0) | ||
112 | |||
109 | /* Fixed logical ports. */ | 113 | /* Fixed logical ports. */ |
110 | #define OVSP_LOCAL ((__u32)0) | 114 | #define OVSP_LOCAL ((__u32)0) |
111 | 115 | ||
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 50d7782d8d7c..6a9b0cb8a1db 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -1040,6 +1040,7 @@ static const struct genl_ops dp_flow_genl_ops[] = { | |||
1040 | static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = { | 1040 | static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = { |
1041 | [OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 }, | 1041 | [OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 }, |
1042 | [OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 }, | 1042 | [OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 }, |
1043 | [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 }, | ||
1043 | }; | 1044 | }; |
1044 | 1045 | ||
1045 | static struct genl_family dp_datapath_genl_family = { | 1046 | static struct genl_family dp_datapath_genl_family = { |
@@ -1098,6 +1099,9 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, | |||
1098 | &dp_megaflow_stats)) | 1099 | &dp_megaflow_stats)) |
1099 | goto nla_put_failure; | 1100 | goto nla_put_failure; |
1100 | 1101 | ||
1102 | if (nla_put_u32(skb, OVS_DP_ATTR_USER_FEATURES, dp->user_features)) | ||
1103 | goto nla_put_failure; | ||
1104 | |||
1101 | return genlmsg_end(skb, ovs_header); | 1105 | return genlmsg_end(skb, ovs_header); |
1102 | 1106 | ||
1103 | nla_put_failure: | 1107 | nla_put_failure: |
@@ -1144,6 +1148,12 @@ static struct datapath *lookup_datapath(struct net *net, | |||
1144 | return dp ? dp : ERR_PTR(-ENODEV); | 1148 | return dp ? dp : ERR_PTR(-ENODEV); |
1145 | } | 1149 | } |
1146 | 1150 | ||
1151 | static void ovs_dp_change(struct datapath *dp, struct nlattr **a) | ||
1152 | { | ||
1153 | if (a[OVS_DP_ATTR_USER_FEATURES]) | ||
1154 | dp->user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]); | ||
1155 | } | ||
1156 | |||
1147 | static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | 1157 | static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) |
1148 | { | 1158 | { |
1149 | struct nlattr **a = info->attrs; | 1159 | struct nlattr **a = info->attrs; |
@@ -1202,6 +1212,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1202 | parms.port_no = OVSP_LOCAL; | 1212 | parms.port_no = OVSP_LOCAL; |
1203 | parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]); | 1213 | parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]); |
1204 | 1214 | ||
1215 | ovs_dp_change(dp, a); | ||
1216 | |||
1205 | vport = new_vport(&parms); | 1217 | vport = new_vport(&parms); |
1206 | if (IS_ERR(vport)) { | 1218 | if (IS_ERR(vport)) { |
1207 | err = PTR_ERR(vport); | 1219 | err = PTR_ERR(vport); |
@@ -1305,6 +1317,8 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1305 | if (IS_ERR(dp)) | 1317 | if (IS_ERR(dp)) |
1306 | goto unlock; | 1318 | goto unlock; |
1307 | 1319 | ||
1320 | ovs_dp_change(dp, info->attrs); | ||
1321 | |||
1308 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); | 1322 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); |
1309 | if (IS_ERR(reply)) { | 1323 | if (IS_ERR(reply)) { |
1310 | err = PTR_ERR(reply); | 1324 | err = PTR_ERR(reply); |
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index ba13be4a680f..62619a4ee649 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h | |||
@@ -88,6 +88,8 @@ struct datapath { | |||
88 | /* Network namespace ref. */ | 88 | /* Network namespace ref. */ |
89 | struct net *net; | 89 | struct net *net; |
90 | #endif | 90 | #endif |
91 | |||
92 | u32 user_features; | ||
91 | }; | 93 | }; |
92 | 94 | ||
93 | /** | 95 | /** |