You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2014/05/15 03:21:39 UTC

[9/9] git commit: Added API for managing ARP packet filters.

Added API for managing ARP packet filters.

Review: https://reviews.apache.org/r/20296


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/336420c6
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/336420c6
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/336420c6

Branch: refs/heads/master
Commit: 336420c66516d09211ecbebf3310b45517e35577
Parents: 6d068b2
Author: Jie Yu <yu...@gmail.com>
Authored: Sun Apr 13 11:42:11 2014 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed May 14 17:38:43 2014 -0700

----------------------------------------------------------------------
 src/Makefile.am                  |   2 +
 src/linux/routing/filter/arp.cpp | 164 ++++++++++++++++++++++++++++++++++
 src/linux/routing/filter/arp.hpp |  84 +++++++++++++++++
 src/tests/routing_tests.cpp      | 106 ++++++++++++++++++++++
 4 files changed, 356 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/336420c6/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index c18ddf0..ddbd82b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -270,6 +270,7 @@ if WITH_NETWORK_ISOLATOR
   libmesos_no_3rdparty_la_SOURCES +=					\
 	linux/routing/utils.cpp						\
 	linux/routing/link/link.cpp					\
+	linux/routing/filter/arp.cpp					\
 	linux/routing/filter/icmp.cpp					\
 	linux/routing/queueing/handle.cpp				\
 	linux/routing/queueing/ingress.cpp
@@ -278,6 +279,7 @@ if WITH_NETWORK_ISOLATOR
 	linux/routing/internal.hpp					\
 	linux/routing/utils.hpp						\
 	linux/routing/filter/action.hpp					\
+	linux/routing/filter/arp.hpp					\
 	linux/routing/filter/filter.hpp					\
 	linux/routing/filter/icmp.hpp					\
 	linux/routing/filter/internal.hpp				\

http://git-wip-us.apache.org/repos/asf/mesos/blob/336420c6/src/linux/routing/filter/arp.cpp
----------------------------------------------------------------------
diff --git a/src/linux/routing/filter/arp.cpp b/src/linux/routing/filter/arp.cpp
new file mode 100644
index 0000000..3f37a83
--- /dev/null
+++ b/src/linux/routing/filter/arp.cpp
@@ -0,0 +1,164 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <linux/if_ether.h>
+
+#include <netlink/errno.h>
+
+#include <netlink/route/tc.h>
+
+#include <netlink/route/cls/basic.h>
+
+#include <stout/error.hpp>
+#include <stout/none.hpp>
+
+#include "linux/routing/internal.hpp"
+
+#include "linux/routing/filter/action.hpp"
+#include "linux/routing/filter/arp.hpp"
+#include "linux/routing/filter/filter.hpp"
+#include "linux/routing/filter/internal.hpp"
+#include "linux/routing/filter/priority.hpp"
+
+#include "linux/routing/queueing/handle.hpp"
+
+using std::string;
+
+namespace routing {
+namespace filter {
+namespace arp {
+
+// The classifier for ARP packet filters contains nothing and is not
+// exposed to the user as we don't care about the content in the ARP
+// packet.
+struct Classifier
+{
+  bool operator == (const Classifier& that) const
+  {
+    return true;
+  }
+};
+
+} // namespace arp {
+
+/////////////////////////////////////////////////
+// Filter specific pack/unpack functions.
+/////////////////////////////////////////////////
+
+namespace internal {
+
+// Encodes the ARP classifier into the libnl filter 'cls'. Each type
+// of classifier needs to implement this function.
+template <>
+Try<Nothing> encode<arp::Classifier>(
+    const Netlink<struct rtnl_cls>& cls,
+    const arp::Classifier& classifier)
+{
+  rtnl_cls_set_protocol(cls.get(), ETH_P_ARP);
+
+  int err = rtnl_tc_set_kind(TC_CAST(cls.get()), "basic");
+  if (err != 0) {
+    return Error(
+        "Failed to set the kind of the classifier: " +
+        string(nl_geterror(err)));
+  }
+
+  return Nothing();
+}
+
+// Decodes the ARP classifier from the libnl filter 'cls'. Each type
+// of classifier needs to implement this function. Returns None if the
+// libnl filter is not an ARP packet filter.
+template <>
+Result<arp::Classifier> decode<arp::Classifier>(
+    const Netlink<struct rtnl_cls>& cls)
+{
+  if (rtnl_cls_get_protocol(cls.get()) == ETH_P_ARP &&
+      rtnl_tc_get_kind(TC_CAST(cls.get())) == string("basic")) {
+    return arp::Classifier();
+  }
+
+  return None();
+}
+
+} // namespace internal {
+
+
+namespace arp {
+
+Try<bool> exists(const string& link, const queueing::Handle& parent)
+{
+  return internal::exists(link, parent, Classifier());
+}
+
+
+Try<bool> create(
+    const string& link,
+    const queueing::Handle& parent,
+    const Option<Priority>& priority,
+    const action::Redirect& redirect)
+{
+  return internal::create(
+      link,
+      Filter<Classifier>(
+          parent,
+          Classifier(),
+          priority,
+          redirect));
+}
+
+
+Try<bool> create(
+    const string& link,
+    const queueing::Handle& parent,
+    const Option<Priority>& priority,
+    const action::Mirror& mirror)
+{
+  return internal::create(
+      link,
+      Filter<Classifier>(
+          parent,
+          Classifier(),
+          priority,
+          mirror));
+}
+
+
+Try<bool> remove(const string& link, const queueing::Handle& parent)
+{
+  return internal::remove(link, parent, Classifier());
+}
+
+
+Try<bool> update(
+    const string& link,
+    const queueing::Handle& parent,
+    const action::Mirror& mirror)
+{
+  return internal::update(
+      link,
+      Filter<Classifier>(
+          parent,
+          Classifier(),
+          None(),
+          mirror));
+}
+
+} // namespace arp {
+} // namespace filter {
+} // namespace routing {

http://git-wip-us.apache.org/repos/asf/mesos/blob/336420c6/src/linux/routing/filter/arp.hpp
----------------------------------------------------------------------
diff --git a/src/linux/routing/filter/arp.hpp b/src/linux/routing/filter/arp.hpp
new file mode 100644
index 0000000..fa0ea6f
--- /dev/null
+++ b/src/linux/routing/filter/arp.hpp
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LINUX_ROUTING_FILTER_ARP_HPP__
+#define __LINUX_ROUTING_FILTER_ARP_HPP__
+
+#include <string>
+
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+
+#include "linux/routing/filter/action.hpp"
+#include "linux/routing/filter/filter.hpp"
+#include "linux/routing/filter/priority.hpp"
+
+#include "linux/routing/queueing/handle.hpp"
+
+namespace routing {
+namespace filter {
+namespace arp {
+
+// Returns true if an ARP packet filter attached to the given parent
+// exists on the link.
+Try<bool> exists(const std::string& link, const queueing::Handle& parent);
+
+
+// Creates an ARP packet filter attached to the given parent on the
+// link which will redirect all ARP packets to the target link.
+// Returns false if an ARP packet filter attached to the given parent
+// already exists on the link. The user can choose to specify an
+// optional priority for the filter.
+Try<bool> create(
+    const std::string& link,
+    const queueing::Handle& parent,
+    const Option<Priority>& priority,
+    const action::Redirect& redirect);
+
+
+// Creates an ARP packet filter attached to the given parent on the
+// link which will mirror all ARP packets to a set of links (specified
+// in the mirror action). Returns false if an ARP packet filter
+// attached to the given parent already exists on the link. The user
+// can choose to specify an optional priority for the filter.
+Try<bool> create(
+    const std::string& link,
+    const queueing::Handle& parent,
+    const Option<Priority>& priority,
+    const action::Mirror& mirror);
+
+
+// Removes the ARP packet filter attached to the parent from the link.
+// Returns false if no ARP packet filter attached to the given parent
+// is found on the link.
+Try<bool> remove(const std::string& link, const queueing::Handle& parent);
+
+
+// Updates the action of the APR packet filter attached to the given
+// parent on the link. Returns false if no ARP packet filter attached
+// to the parent is found on the link.
+Try<bool> update(
+    const std::string& link,
+    const queueing::Handle& parent,
+    const action::Mirror& mirror);
+
+} // namespace arp {
+} // namespace filter {
+} // namespace routing {
+
+#endif // __LINUX_ROUTING_FILTER_ARP_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/336420c6/src/tests/routing_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/routing_tests.cpp b/src/tests/routing_tests.cpp
index de6d9e3..cc3d6da 100644
--- a/src/tests/routing_tests.cpp
+++ b/src/tests/routing_tests.cpp
@@ -33,6 +33,7 @@
 
 #include "linux/routing/utils.hpp"
 
+#include "linux/routing/filter/arp.hpp"
 #include "linux/routing/filter/icmp.hpp"
 
 #include "linux/routing/link/link.hpp"
@@ -292,6 +293,111 @@ TEST_F(RoutingVethTest, ROOT_LinkMTU)
 }
 
 
+TEST_F(RoutingVethTest, ROOT_ARPFilterCreate)
+{
+  ASSERT_SOME(link::create(TEST_VETH_LINK, TEST_PEER_LINK, None()));
+
+  EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
+  EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
+
+  ASSERT_SOME_TRUE(ingress::create(TEST_VETH_LINK));
+
+  EXPECT_SOME_TRUE(arp::create(
+      TEST_VETH_LINK,
+      ingress::HANDLE,
+      None(),
+      action::Redirect(TEST_PEER_LINK)));
+
+  EXPECT_SOME_TRUE(arp::exists(TEST_VETH_LINK, ingress::HANDLE));
+}
+
+
+TEST_F(RoutingVethTest, ROOT_ARPFilterCreateDuplicated)
+{
+  ASSERT_SOME(link::create(TEST_VETH_LINK, TEST_PEER_LINK, None()));
+
+  EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
+  EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
+
+  ASSERT_SOME_TRUE(ingress::create(TEST_VETH_LINK));
+
+  set<string> links;
+  links.insert(TEST_PEER_LINK);
+
+  EXPECT_SOME_TRUE(arp::create(
+      TEST_VETH_LINK,
+      ingress::HANDLE,
+      None(),
+      action::Mirror(links)));
+
+  EXPECT_SOME_TRUE(arp::exists(TEST_VETH_LINK, ingress::HANDLE));
+
+  EXPECT_SOME_FALSE(arp::create(
+      TEST_VETH_LINK,
+      ingress::HANDLE,
+      None(),
+      action::Redirect(TEST_PEER_LINK)));
+}
+
+
+TEST_F(RoutingVethTest, ROOT_ARPFilterRemove)
+{
+  ASSERT_SOME(link::create(TEST_VETH_LINK, TEST_PEER_LINK, None()));
+
+  EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
+  EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
+
+  ASSERT_SOME_TRUE(ingress::create(TEST_VETH_LINK));
+
+  set<string> links;
+  links.insert(TEST_PEER_LINK);
+
+  EXPECT_SOME_TRUE(arp::create(
+      TEST_VETH_LINK,
+      ingress::HANDLE,
+      None(),
+      action::Mirror(links)));
+
+  EXPECT_SOME_TRUE(arp::exists(TEST_VETH_LINK, ingress::HANDLE));
+  EXPECT_SOME_TRUE(arp::remove(TEST_VETH_LINK, ingress::HANDLE));
+  EXPECT_SOME_FALSE(arp::exists(TEST_VETH_LINK, ingress::HANDLE));
+}
+
+
+TEST_F(RoutingVethTest, ROOT_ARPFilterUpdate)
+{
+  ASSERT_SOME(link::create(TEST_VETH_LINK, TEST_PEER_LINK, None()));
+
+  EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
+  EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
+
+  ASSERT_SOME_TRUE(ingress::create(TEST_VETH_LINK));
+
+  set<string> links;
+  links.insert(TEST_PEER_LINK);
+
+  EXPECT_SOME_FALSE(arp::update(
+      TEST_VETH_LINK,
+      ingress::HANDLE,
+      action::Mirror(links)));
+
+  EXPECT_SOME_TRUE(arp::create(
+      TEST_VETH_LINK,
+      ingress::HANDLE,
+      None(),
+      action::Redirect(TEST_PEER_LINK)));
+
+  EXPECT_SOME_TRUE(arp::exists(TEST_VETH_LINK, ingress::HANDLE));
+
+  EXPECT_SOME_TRUE(arp::update(
+      TEST_VETH_LINK,
+      ingress::HANDLE,
+      action::Mirror(links)));
+
+  EXPECT_SOME_TRUE(arp::exists(TEST_VETH_LINK, ingress::HANDLE));
+}
+
+
 TEST_F(RoutingVethTest, ROOT_ICMPFilterCreate)
 {
   ASSERT_SOME(link::create(TEST_VETH_LINK, TEST_PEER_LINK, None()));