Software Defined Network week 3(一)

1 篇文章 0 订阅

Learning Objectives

  • Review how an SDN controller can populate a switch’s forwarding table.
  • Determine how an SDN controller can be used to control multiple switches in a single network, and why that might be a good thing to do.
  • Gain experience setting up a controller and basic switch environment.
  • Compare the design tradeoffs between some of the more commonly used SDN/OpenFlow controllers.
  • Set up controller in Mininet that can perform basic operations, like switch-table population and firewalling.

Key Terms

  • OpenFlow Specification: The official protocol specification that determines the formats for messages between the controller and the switch.
    Version 1.0: The first “official release” of the OpenFlow protocol specification that is implemented on all major hardware and software switches, including Open vSwitch. Most controllers also support the OpenFlow 1.0 specification.

Version 1.3: A recent version of the OpenFlow protocol specification, which allows for packets to be pipelined through multiple sequences of actions.

Version 1.4: The latest version of the OpenFlow protocol specification, which provides support for transactional rule changes, management of switch table space, etc.

  • Flow table caching: The process by which flow table decisions are cached at the switch, to prevent all packets from having to be forwarded through the controller.
  • Control channel: The communications channel that an SDN controller uses to communicate with SDN-capable switches.
  • Controller overhead: Typically refers to the overhead that results when a switch does not have a flow table entry for a packet, causing the packet to be sent to the controller for processing.
  • OpenStack: A cloud operating system that makes use of network virtualization and OpenFlow to present an abstraction of a logical pool of resources.

The Control Plane

在这里插入图片描述
在这里插入图片描述
The controller speaks to the OpenFlow switch over a secure channel and the protocol effectively instructs the OpenFlow switch to update its flow table entries to take different actions on various traffic flows that pass through the switch.

The purpose of the control channel is effectively to update this flow table and all of the logic concerning how the flow table entries are updated are contained at the controller. All of the smarts of the network are resident at the controller and the switches job is simply reduced to forwarding traffic based on the flow table entries that the controller installs.
The OpenFlow protocol specification defines a number of things including the complements of the switch, the message format, and what types of actions the flow table should be capable of performing.
在这里插入图片描述
Let’s take a closer look at certain aspects of the OpenFlow protocol specification. The protocol specification defines two switch components. The first is the flow table, the flow table performs packet look up. The lookup function compares the fields in each packet to a flow table that resides in the switch and looks for a match.
In other words, it looks to see whether or not the headers of the packets that are passing through the switch match any of the entries in the switch’s flow table.
The actions that the switch takes then depend on how or whether the packets passing through that switch match any of those particular flow table entries.
If there is no match, the traffic is sent to the controller.
The other aspect of an SDN switch is the secure channel, which is how the switch communicates with the external controller. Let’s take a quick look at how OpenFlow performs matching using the flow table entries in a particular switch.
This particular flowchart, which is taken from the OpenFlow version 1.0 specification, specifies how a switch should process a packet as it arrives.
在这里插入图片描述
This particular flowchart, which is taken from the OpenFlow version 1.0 specification, specifies how a switch should process a packet as it arrives.
When a packet arrives at the switch, it parses the header fields, and based on the values of those header fields, it will attempt to match that packet against flow table entries in any one of several flow tables. If there is no match in any of those tables, the traffic is sent to the controller. Otherwise, actions are performed based on the actions that are specified in the matching flow table entries. So to summarize, packet header fields are matched against one of the N tables and if there’s no match the packet is sent to the controller. For scalability reasons, it does make sense to try to match as many packets in the switch as possible to avoid having too much traffic diverted to the controller.

在这里插入图片描述
Let’s take a closer look at the match fields that are part of the OpenFlow 1.0 specification.
The specification defines a 12-tuple. In other words, 12 different fields in a packet header on which a flow table entry could match.
In addition to the ten that are shown in this figure, there are also two extra ones. Other fields that the switch can match on include the incoming switchboard, the source and destination MAC address, the ethernet type, the VLAN ID, the source and destination IP address, the protocol type, for example, whether or not the packet is a TCP or a UDP packet and if it’s a TCP packet, the source and destination port. Once the switch identifies a matching flow table entry, it will perform the action that is specified in that flow table entry.

在这里插入图片描述
Two mandatory actions in the OpenFlow protocol specification are forwarding the packet and dropping it.
Now forwarding can include several possibilities. One, is to forward the packet out all of the interfaces not including the interface on which the packet arrived.(除了来的端口都转发)
Another is to simply encapsulate the packet and send it to the controller. (封装包送至controller)
Another option is to divert the packet to the switch’s local networking stack.(将数据包转移到交换机的本地网络堆栈?)
Another is to simply just perform the actions in the flow table. Finally, the switch could send the packet back out the input port.
The OpenFlow 1.0 specification also specifies some optional actions such as forwarding the packet as the switch normally would and forwarding the packet according to a spanning tree.
The other mandatory action is the drop action whereby a flow entry with no specified action indicates that all matching packets for that flow table entry should be dropped.没指定就丢弃
在这里插入图片描述
In addition, there are several optional actions that the OpenFlow 1.0 specification describes. One is the modify action whereby the switch might modify various packet header values such as the VLAN ID or the destination IP address.
Modifying the destination IP address could be useful, for example, for performing higher level operations such as wide area network load balancing. 现在粗浅的理解就是负载均衡通过改目标IP地址实现
Another optional action is to send the packet through a queue that’s attached to say an output port. 这种之前没见过诶
One possible use for this action would be to apply quality of service or traffic shaping.
在这里插入图片描述
An OpenFlow switch by default listens on a control port and even in the absence of a controller we can talk to the switch using a program called dpctl. The dpctl programs allows us to perform operations such as inspecting the flow table entries on the switch, modifying flow table entries and so forth.
Let’s take a quick look at dpctl in action using the topology that we’ve shown here.
We can tell mininet to start a single network with three hosts all connected by a single switch where the single switch is controlled by a remote controller as can be seen here with the controller remote option. We can now use dpctl to connect to the controller.

ovs-vsctl show在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
One is the notion of an action set whereby the switch might perform multiple actions on each packet.

Another is a notion of a group, which is essentially a list of action sets. A group effectively allows the switch to refer to a common set of actions that might be performed on multiple sets of matching flows. In the OpenFlow 1.3 pipeline each table in the pipeline can update packet header fields and potentially add to the set of actions that will be performed on the packet before it is sent on the output port.
在这里插入图片描述
这一段不是很懂
There are various options for specifying actions in an action group.
One option is to execute all of the action sets in a particular group.
This option is useful for implementing multicast whereby one packet might be cloned for each action set in the group. (多播时用)
Another example of a group option is something called an indirect group whereby the one action set in the group is executed. This might be useful for performing the same set of operations on multiple flow entries. For example, if a switch had multiple flow table entries all of which were to be forwarded to the same next top IP address, indirect groups would allow the switch to point all of those flow table entries to the same indirect group.(如果很多表项都是要转发到同样的IP地址,交换机可以将这些表项指向同一个indirect groups)
在这里插入图片描述
Various example actions include decrementing the TTL, copying the TTL to various parts of a header, applying MPLS tags to a packet, and applying quality of service actions. There are many more details about the OpenFlow specifications in the OpenFlow specification White Papers, which are available on the Open Network Foundation webpage.
应该是openflow流表修改的更多高级操作,之后还是要好好看看的

在这里插入图片描述
It is worthwhile noting that there are other SDN control architectures.
在这里插入图片描述
We have looked at several in the course already as far as history is concerned. For example, the RCP is one example of an SDN control architecture that is very specific to the border gateway protocol. More recently, various vendors have been devising their own control architectures. Juniper’s Contrail Controller uses XMPP as the control plane and has mechanisms for instantiating virtual networks at both layer two and layer three. Much of the software for Juniper’s Contrail Controller will be contributed to the OpenDaylight community, which is a community devoted to maintaining open source implementations of various SDN control architectures.

Another SDN control architecture is Cisco’s Open Network Environment, which specifies a centralized software controller, a programmable data plane, and the ability to provide virtual overlays.
在这里插入图片描述
In summary, in this lecture we’ve looked at various basics of the control plane. We’ve explored the various components of an OpenFlow switch including the secure channel, the flow tables, as well as the newer group tables which are under development as part of more modern OpenFlow protocol specifications.

It’s worth noting that the OpenFlow protocol is evolving. And in this course, when we get our hands dirty with specific OpenFlow switches, and in particular Open vSwitch, that particular switch implementation has not implemented many of the options specified in later protocol specifications.(当时还有很多功能没有实现)

Most of what we will deal with in this course relates to the OpenFlow version 1.0 specification. We took a brief look at dpctl, which connects directly to a switch and can be used to poll and manipulate flow table entries. In the next lesson, we’ll explore different SDN controllers that can be used for more sophisticated network control logic.

Group Table

Group Table给OpenFlow Switch提供了更加高级的数据包转发特性(比如select或者all),其由多个Group Entries组成,而每个Group Entry结构如下所示:

每个Group Entry根据其Group Identifier来唯一定位,每项具体说明如下:

1)Group Identifier:一个32位无符号整数,Group Entry的唯一标识。

2)Group Type:决定了Group的语义,通俗地讲,就是表明了对数据包的处理行为,具体参考下文。

3)Counters:被该Group Entry处理过的数据包的统计量。

4)Action Buckets:一个Action Bucket的有序列表,每个Action Bucket又包含了一组Action集合及其参数。

2、Group Types

一个OpenFlow Switch不需要支持下列所有的Group Types,但必须支持下面加黑的类型:

1)all:Group Table中所有的Action Buckets都会被执行,这种类型的Group Table主要用于数据包的多播或者广播。数据包对于每一个Action Bucket都会被克隆一份,进而克隆体被处理。如果一个Action Bucket显示地将数据包发回其 ingress port,那么该数据包克隆体会被丢弃;但是,如果确实需要将数据包的一个克隆体发送回其 ingress port,那么该Group Table里就需要一个额外的Action Bucket,它包含了一个 output action 将数据包发送到 OFPP_IN_PORT Reserved Port。

2)select:仅仅执行Group Table中的某一个Action Bucket,基于OpenFlow Switch的调度算法,比如基于用户某个配置项的hash或者简单的round robin,所有的配置信息对于OpenFlow Switch来说都是属于外部的。当将数据包发往一个当前down掉的port时,Switch能将该数据包替代地发送给一个预留集合(能将数据包转发到当前live的ports上),而不是毫无顾忌地继续将数据包发送给这个down的port,这或许可以明显降低由于一个down的link或者switch带来的灾难。 能够应对突发down

3)indirect:执行Group Table中已经定义好的Action Bucket,这种类型的Group Table仅仅只支持一个Action Bucket。允许多个Flow Entries或者Groups 指向同一个通用的 Group Identifier,支持更快更高效的聚合。这种类型的Group Table与那些仅有一个Action Bucket的Group Table是一样的。

4)fast failover:执行第一个live的Action Bucket,每一个Action Bucket都关联了一个指定的port或者group来控制它的存活状态。Buckets会依照Group顺序依次被评估,并且第一个关联了一个live的port或者group的Action Bucket会被筛选出来。这种Group类型能够自行改变Switch的转发行为而不用事先请求Remote Controller。如果当前没有Buckets是live的,那么数据包就被丢弃,因此这种Group必须要实现一个管理存活状态的机制。

Overview of SDN Controllers

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
One is the choice of programming language which can sometimes, but not always affect the performance of the controller itself. There’s also how long it takes to figure out how to use the controller. If you’re trying to do something just quick and dirty for prototyping, then you might want to use a controller with a much easier learning curve. Another thing to consider is the user base and the community support behind the controller. Finally different controllers have different focuses in terms of the south bound APIs that are supported. The north bound API or the policy layer whether or not their support for open stack or multi tenant cloud environments. And whether or not the controller was intended for use in education, research, or production.
在这里插入图片描述
In NOX, users implement control in C++. NOX itself supports OpenFlow version 1.0, and a fork of NOX called CPqD supports 1.1, 1.2, and 1.3. In NOX the programmer writes a control program that registers for certain events. Such as packet arrivals. Or topology changes. And the programmer then writes event handlers that respond to those different events. Might want to use NOX if you already know C++. And you’re willing to use low-level facilities and semantics of OpenFlow, such as functions that directly modify the switch flow table.
先定义事件,然后根据事件定义操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
POX is essentially NOX in Python. It currently supports only version 1.0.
An advantage of POX is that it’s widely used, maintained and supported and it’s relatively easy to read and write code. The main disadvantage of POX is performance. POX is the main controller that we’ll be using in this course. Mainly because it has a relatively easy learning curve relative to some of the other controllers. And there are some interesting policy layers such as Pyretic that are built on top of POX. You might want to use POX if you already know or can quickly learn Python and are not concerned about controller performance. It’s commonly used in research, for experimentation and for demonstrations as well as for learning concepts such as the concepts that we are learning in this course.
在这里插入图片描述
在这里插入图片描述
Ryu is an open source Python controller. It supports all versions of OpenFlow from 1.0 to 1.4 as well as various mysteria extensions. It also has OpenStack integration, in some sense it aims to be an operating system for SDN. And it’s main advantages are the support for all these versions of OpenFlow and it’s OpenStack integration. A disadvantage of Ryu with respect to some of the other commercial grade controllers is performance.
在这里插入图片描述
Floodlight is an open-source Java controller that supports OpenFlow 1.0. It’s a fork from the Beacon Java OpenFlow controller. And is maintained by Big Switch. Some of the advantages include good documentation and integration with the REST API. It’s also production level, and supports and provides support for OpenStack and Multi-Tenant Clouds.However, it has a fairly steep learning curve.在这里插入图片描述

You might want to use Floodlight if you know Java, if you need production level performance and support, or if you will use the REST API to interact with the controller.
在这里插入图片描述
Another controller that is in active development is OpenDaylight. The goal of the OpenDaylight project is to provide a common industrt supported platform with a robust, extensible open source codebase and common abstractions for northbound capabilities. OpenDaylight has many advantages including widespread industry acceptance and integration with OpenStack and other types of cloud applications.
However, it’s extremely complex. The documentation is rather poor. And there’s a very steep learning curve. The complexity and steep learning curve of OpenDaylight are two reasons that we’re not using it as the main controller for this course. However, I’ve added a lecture this year, to cover the basics of OpenDaylight based on a tutorial that’s being provided by SDN Hub. We’ll talk about that in the next lesson.
Another commercial great controller that’s worth mentioning is HP VAN. Both OpenDaylight and HP VAN were originally based on the source code of a controller called Beacon, and hence have many similarities both with Beacon and with each other. 在这里插入图片描述
You might want to use OpenDaylight if you know Java. If you need production level performance and support. If you need support for cloud applications, OpenStack and so forth. If you need modular functions. Such as the ability to plug different types of functionality including both northbound and southbound functionality into the same controller. Or if you need applications that are already supported or implemented by vendors.
在这里插入图片描述
It’s worth mentioning a library under development called LoxiGen. Which actually generates OpenFlow language specific bindings, for different controllers. The idea is that one could provide a wire protocol description. Of a control protocol. And the output would be protocol specific bindings in different languages. LoxiGen currently generates OpenFlow version 1.0 to 1.31 bindings in C for Indigo, in Java for Floodlight, Python for OFTest. And it also generates a binding for Wireshark and Lua. In theory, one of the appeals of LoxiGen is that it should support the evolvability of many different controllers. As the OpenFlow wire protocol continues to evolve, in theory one can simply use LoxiGen to upgrade the version of the OpenFlow protocol that the controller supports.
在这里插入图片描述
In summary, there are a lot of different controllers. And your choice of controller may depend on your needs, your language, and so forth. Thus far, we’ve focused mainly on the controller’s support for different Southbound API implementations such as different versions of OpenFlow. However, it’s worth noting that Southbound APIs are becoming much broader than just OpenFlow. And we’ll talk about that more in the next lesson when we talk about OpenDailight which supports a much broader range of Southbound APIs. Later in the course we’ll talk about various controllers emerging support for different kinds of Northbound APIs or policy layers that sit on top of these controllers.

Customizing SDN Control (Part 1: Switching)

在这里插入图片描述
在这里插入图片描述
两种不同的控制方式
A hub which simply forwards all traffic out all of the output ports and a learning switch which learns forwarding table entries based on the ports on which incoming packets arrive.
在这里插入图片描述
连接的是6633,看流表用的是6634?
在这里插入图片描述
In a hub, no forwarding information is actually stored at the switch that connects the hosts and the network. Therefore, when an input packet arrives on a particular port, the switch simply forwards that packet out all of the output ports.没有转发信息,直接送到所有的端口
在这里插入图片描述
代码在hub.py pox/pox/forwarding

def launch (reactive = False):
  if reactive:
    core.openflow.addListenerByName("PacketIn", _handle_PacketIn)
    log.info("Reactive hub running.")
  else:
    core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
    log.info("Proactive hub running.")

One is a method called launch, which just adds a listener that listens for OpenFlow switches to connect to it.
在这里插入图片描述

在这里插入图片描述

def _handle_ConnectionUp (event):
  """
  Be a proactive hub by telling every connected switch to flood all packets
  """
  msg = of.ofp_flow_mod() # 修改流表
  msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) # send the packets on all of the output ports
  event.connection.send(msg)
  log.info("Hubifying %s", dpidToStr(event.dpid))

he handle connection up method simply creates a flow modification message that we will send back to the Open vSwitch, telling the switch to modify its flow table entries.
So we first create the message, and in that message, we append a specific action which simply is to send the packets on all of the output ports. Once we’ve created that OpenFlow flow table modification method, we simply send that message to the switch on the connection that we have from the Open vSwitch.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
So if you recall, when a packet arrives on an input port at a hub, the hub simply forwards that packet on all of the output ports.
A learning switch, on the other hand, behaves a little differently because when that input packet arrives, the switch learns how to reach the particular destination that sent the packet to the switch.
For example, in the figure here, we see that a packet arrives from A. At that point, the switch can examine the source MAC address for that packet and then determine that packets that are destined for that source MAC address for A should be sent on the output port on the left side of the switch here.检查源MAC地址,送回到那个MAC地址的时候就走那个端口
In other words, each incoming frame causes the switch to create a new flow table entry. To cause the POX Controller to induce that behavior on the Open vSwitch, we attach the POX Controller as before, but instead of running the hub code that we just looked at we are going to run a different set of methods which is in the l2_learning.py file in the POX distribution. Let’s jump in and take a quick look at the learning switch algorithm that is implemented in that Python file.
在这里插入图片描述
The algorithm has several steps.
The first step is to use the source address of the packet and the switch port to update the address and port table that the controller itself maintains as a hash table. 控制器维护了一张hash表存Mac地址和端口号
The second is to drop certain types of packets.
The third is to check whether the destination for the packet is a multicast destination. If it is, the controller instructs the switch to flood the packet on all output ports. If the destination address for the packet is not already contained in the hash table that’s being maintained at the controller for mapping addresses to ports, then the controller instructs the switch to behave like a hub by flooding the traffic out all output ports. (没有记录就广播)If the output port is the same as the input port, the controller instructs the switch to drop the packet to avoid loops.(目的端口和源端口一致则丢弃) Otherwise, the controller sends a flow table modification entry to the switch. That flow table modification entry is similar to the one we looked at in the hub example, but the difference is that the flow table entry is specific to the port on which the packet arrived and that address that’s contained in the source address field of the incoming packet.(不同之处在于在表彰只增加和源地址和目的端口有关的)
What the controller does is take that source address for the packet and the incoming port on which the packet arrived and inserts a flow table entry in the switch that instructs all future packets destined for that address to be forwarded only out that output port rather than being flooded out all output ports. 不就是网桥的那个操作吗 呵呵哒
Let’s clean up the Mininet topology that we had before and start it again.
在这里插入图片描述
fuser -k 6633/tcp 杀掉重来
或者sudo killall controller
pingall后查看流表
在这里插入图片描述
Now, as before we have a launch method which registers the l2 learning object with the core POX Controller.
Upon being instantiated that object adds a listener to ensure that it can handle connection up events from OpenFlow switches that try to connect to this controller. Upon a connection attempt from an OpenFlow switch, this object then instantiates the learning switch object and passes the connection event to that object. When we dig into that particular object, we can see that upon instantiation we create that hash table mapping the addresses to ports.
先注册

def launch (transparent=False, hold_down=_flood_delay, ignore = None):
  """
  Starts an L2 learning switch.
  """
  try:
    global _flood_delay
    _flood_delay = int(str(hold_down), 10)
    assert _flood_delay >= 0
  except:
    raise RuntimeError("Expected hold-down to be a number")

  if ignore:
    ignore = ignore.replace(',', ' ').split()
    ignore = set(str_to_dpid(dpid) for dpid in ignore)

  core.registerNew(l2_learning, str_to_bool(transparent), ignore) # 注册 
class l2_learning (object):
  """
  Waits for OpenFlow switches to connect and makes them learning switches.
  """
  def __init__ (self, transparent, ignore = None):
    """
    Initialize

    See LearningSwitch for meaning of 'transparent'
    'ignore' is an optional list/set of DPIDs to ignore
    """
    core.openflow.addListeners(self)   # 实例化后增加一个监听确保能和switch连上
    self.transparent = transparent
    self.ignore = set(ignore) if ignore else ()
    
   def _handle_ConnectionUp (self, event):
    if event.dpid in self.ignore:
      log.debug("Ignoring connection %s" % (event.connection,))
      return
    log.debug("Connection %s" % (event.connection,))
    LearningSwitch(event.connection, self.transparent) # switch尝试连接后,实例化对象learning switch,将连接事件传递给对象

We add a listener for packet in messages and then we implement the packet in handler.

def __init__ (self, connection, transparent):
    # Switch we'll be adding L2 learning switch capabilities to
    self.connection = connection
    self.transparent = transparent

    # Our table
    self.macToPort = {}	# 创建从地址映射到端口的hash表

    # We want to hear PacketIn messages, so we listen
    # to the connection
    connection.addListeners(self)  #  add a listener for packet in messages 

    # We just use this to know when to log a helpful message
    self.hold_down_expired = _flood_delay == 0

    #log.debug("Initializing LearningSwitch, transparent=%s",
    #          str(self.transparent))

具体的转发算法

self.macToPort[packet.src] = event.port # 1 assign an entry in the MAC to port table that maps that packet's source MAC address to the port on which the packet arrived.

    if not self.transparent: # 2
      if packet.type == packet.LLDP_TYPE or packet.dst.isBridgeFiltered():
        drop() # 2a
        return

    if packet.dst.is_multicast:
      flood() # 3a   to flood if the packet's destination is a multicast packet,
    else:
      if packet.dst not in self.macToPort: # 4
        flood("Port for %s unknown -- flooding" % (packet.dst,)) # 4a  to flood if the packet's destination is not already in the MAC address to output port mapping,
      else:
        port = self.macToPort[packet.dst]
        if port == event.port: # 5
          # 5a is the same as the port on which the packet arrived
          log.warning("Same port for packet from %s -> %s on %s.%s.  Drop."
              % (packet.src, packet.dst, dpid_to_str(event.dpid), port))
          drop(10)
          return
        # 6 installing a flow table entry in the Open vSwitch that matches on the particular packet properties and sends the packet out the output port corresponding to the port that it just learned that it should send future packets out on based on the port on which the packet arrived
        log.debug("installing flow for %s.%i -> %s.%i" %
                  (packet.src, event.port, packet.dst, port))
        msg = of.ofp_flow_mod()
        msg.match = of.ofp_match.from_packet(packet, event.port)
        msg.idle_timeout = 10
        msg.hard_timeout = 30
        msg.actions.append(of.ofp_action_output(port = port))
        msg.data = event.ofp # 6a  once that flow modification message is created, the controller sends it to the switch. 
        self.connection.send(msg)

以下是上述代码的具体描述
The first step being to assign an entry in the MAC to port table that maps that packet’s source MAC address to the port on which the packet arrived. To drop certain types of packets, to flood if the packet’s destination is a multicast packet, to flood if the packet’s destination is not already in the MAC address to output port mapping, to check whether the designated output port, if it exists, is the same as the port on which the packet arrived and to drop the packet if the input port and the output port are the same. And finally, installing a flow table entry in the Open vSwitch that matches on the particular packet properties and sends the packet out the output port corresponding to the port that it just learned that it should send future packets out on based on the port on which the packet arrived. Finally, once that flow modification message is created, the controller sends it to the switch.

在这里插入图片描述

Customizing SDN Control (Part 2: Firewalls)

防火墙的实现简而言之就是建立了一个hash table,存了(switch,source MAC)-> True/False 只要不是True的包都drop,否则forward
在这里插入图片描述
So to review what we did in the last lesson, we used the POX controller to install simple flow table rules at the switch that matched on the MAC destination address, and took the particular action of forwarding the packet out a particular port. More sophisticated switching is also possible. We can, for example, install flow table rules that match on many more specific fields in the packet header. Thus allowing the switch to make specific forwarding decisions for different flows.
We can also use flow rules to implement a firewall. For example, we could have the switch make forwarding or drop decisions, based on the value of the source MAC address. In this lesson, we will explore how to make simple changes to the layer two learning switch, to implement this firewall example.
在这里插入图片描述
Again we have a switch that connects three hosts, and we’ll attached a controller to that switch. But instead of attaching a controller that performs simply layer two switching, we will augment, the functions being performed by that controller, so that it checks the source MAC address of incoming packets. And decides whether to forward or drop the packet, based on the value of that source MAC address. If the controller decides that the packet should be forwarded, then it proceeds to perform the layer two switching functions as before.
在这里插入图片描述

在这里插入图片描述
First, we need a hash table that stores key value pairs. In particular, that hash table must map the switch identifier and the source MAC address of the packet to a true/false value indicating whether the packet should be forwarded or dropped. (没有Firewalls entry 就扔掉,或者值为false)
The controller will decide to drop the packet if there’s a firewall entry that maps to false or if there is no firewall entry for that source MAC address.
The controller will decide to forward the traffic if there is a firewall entry that maps to true.
在这里插入图片描述
我在forwarding文件夹下复制了Nick的文件,然后用forwarding.firewall来建立连接

# Get the DPID of the Switch Connection
    dpidstr = dpid_to_str(event.connection.dpid)

    # Check the Firewall Rules We have simply added a rule that checks whether or not there is a firewall entry for that source MAC address at that switch. If the entry returns false, the switch drops the packet.
    if self.CheckRule(dpidstr, packet.src) == False:
      drop()
      return

    if not self.transparent: # 2
      if packet.type == packet.LLDP_TYPE or packet.dst.isBridgeFiltered():
        drop() # 2a
        return

    if packet.dst.is_multicast:
      flood() # 3a
    else:
      if packet.dst not in self.macToPort: # 4
        flood("Port for %s unknown -- flooding" % (packet.dst,)) # 4a
      else:
        port = self.macToPort[packet.dst]
        if port == event.port: # 5
          # 5a
          log.warning("Same port for packet from %s -> %s on %s.%s.  Drop."
              % (packet.src, packet.dst, dpid_to_str(event.dpid), port))
          drop(10)
          return
        # 6
        log.debug("installing flow for %s.%i -> %s.%i" %
                  (packet.src, event.port, packet.dst, port))
        msg = of.ofp_flow_mod()
        msg.match = of.ofp_match.from_packet(packet, event.port)
        msg.idle_timeout = 10
        msg.hard_timeout = 30
        msg.actions.append(of.ofp_action_output(port = port))
        msg.data = event.ofp # 6a
        self.connection.send(msg)

So you can recognize from before the first step of the switching algorithm that maps the packet source MAC address to the incoming port and the subsequent steps that the switch takes. We have simply added a rule that checks whether or not there is a firewall entry for that source MAC address at that switch. If the entry returns false, the switch drops the packet.
Otherwise, it continues as before.

 # Our table
    self.macToPort = {}

    # Our firewall table  the hash table stores mappings for particular source MAC addresses
    self.firewall = {}

    # Add a Couple of Rules
    self.AddRule('00-00-00-00-00-01',EthAddr('00:00:00:00:00:01'))
    self.AddRule('00-00-00-00-00-01',EthAddr('00:00:00:00:00:02'))

    # We want to hear PacketIn messages, so we listen
    # to the connection
    connection.addListeners(self)

    # We just use this to know when to log a helpful message
    self.hold_down_expired = _flood_delay == 0

Let’s take a quick look at what we had to do to implement check rule. Here, we made a simple change to add a hash table. The hash table stores mappings for particular source MAC addresses. We can manipulate the hash table with the add rule method, which takes as input, the ID of the switch, a source MAC address, and a true or false value indicating whether or not the package should be forwarded.

 # function that allows adding firewall rules into the firewall table
  def AddRule (self, dpidstr, src=0,value=True):
    self.firewall[(dpidstr,src)]=value
    log.debug("Adding firewall rule in %s: %s", dpidstr, src) 

The check rule function simply checks to see whether the hash table has an entry for that particular switch ID and the source MAC address, and if it does have an entry, it checks to see whether the entry is true or false. The function returns true only if the firewall hash table has an entry for that source MAC address that maps to true.

# check if packet is compliant to rules before proceeding
  def CheckRule (self, dpidstr, src=0):
    try:
      entry = self.firewall[(dpidstr, src)]
      if (entry == True):
        log.debug("Rule (%s) found in %s: FORWARD",
                  src, dpidstr)
      else:
        log.debug("Rule (%s) found in %s: DROP",
                  src, dpidstr)
      return entry
    except KeyError:
      log.debug("Rule (%s) NOT found in %s: DROP",
                src, dpidstr)
      return False

In addition to defining the methods for manipulating the firewall, I’ve also added a couple of rules to our firewall for that particular switch. Which effectively allow packets from hosts with MAC address of one or two to forward packets through that switch. All other traffic will be dropped.


    # Add a Couple of Rules
    self.AddRule('00-00-00-00-00-01',EthAddr('00:00:00:00:00:01'))
    self.AddRule('00-00-00-00-00-01',EthAddr('00:00:00:00:00:02'))

在这里插入图片描述
在这里插入图片描述
We can also see from the debugging messages that the controller decided to forward or drop different packets depending on the value of the source MAC address of the incoming packet.
It is also interesting to note that when the controller decides to forward a packet, it also installs a rule in the switch that allows that packet to be forwarded.
在这里插入图片描述
As long as that flow table entry remains in the switch, all packets that match that flow can continue to be forwarded at the switch. To see the effect that, that behavior has on performance, let’s have host one ping host two. So we can see that initially the first packet experiences very high latency. That is because that packet is redirected to the controller.
Once the controller decides, however, that host one can send traffic to host two and vice versa and those rules are installed in the switch, packets are forwarded directly by the switch until that flow table entry expires.
在这里插入图片描述
And you can see that at about 30 seconds the flow table entry expires again and we see relatively higher latency between the two end hosts because the traffic is redirected to the controller.
在这里插入图片描述
It’s very important to limit the data traffic that gets sent to the controller. As we can see, traffic that gets sent to the controller experiences a much higher latency than traffic that can be forwarded directly through the switch.
Therefore, when the controller decides to forward or drop the traffic, the switch’s flow table is modified.
Those modifications then prevent data traffic from being redirected to the controller, for as long as that flow table entry remains in the switch.
在这里插入图片描述
In summary, we’ve seen that customizing control is very easy with SDN. We’ve made a few small changes to the layer two switch to enable firewall capabilities.
We’ve explored how we can implement this type of alternate control. And we’ve turned a switch into a firewall in less than 40 lines of Python code.
We’ve also demonstrated the performance benefits associated with caching forwarding decisions at the switch, to avoid having to send data traffic to the controller whenever possible.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从控制器向交换机(或直接用 OvS 里的命令行工具给自己)下发流表时,有两个关于事件的参数值得注意:

idle_timeout,空闲时间,如值为 10,表示若某条流表在最近 10s 内没有被匹配过则删除。
hard_timeout,存活时间,如值为 10,则从该流表被安装经过 10s 后无论被使用情况如何,立即被删除。
而如果在交换机上查看流表,会发现除以上两个时间以外,还有两个:

idle_age,未命中时间,如值为 10,表示已经有 10s 没有匹配到过这条流表了。当这个值等于 idle_timeout 时,这条流表就真的失效了。
duration,流表年龄,指的是流表自从安装到交换机上总共所经过的时间。

作者:顽强的猫尾草
链接:https://www.jianshu.com/p/22e6feb2c662
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
addListener确保和交换机顺利connect
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值