예제 #1
0
 def on_readable(self, fd):
    # Handle input on stdin of the format:
    # NAME (add|delete) IPADDR INTERFACE
    # and adds/deletes a flow that matches on that destination ip address
    # and outputs that flow on the given interface
    buf = os.read(fd, 4096).strip()
    if not buf:
       self.agentMgr_.exit()
    for line in buf.split("\n"):
       if not line:
          continue
       m = re.search("(\S+) (add|delete) (\d+.\d+.\d+.\d+) +(\S+)", line)
       if not m:
          print "Could not match line:", line
          continue
       name = m.group(1)
       operation = m.group(2)
       if operation == "add":
          match = createMatch(ipDst=m.group(3),
                              ipDstMask="255.255.255.255")
          outputIntf = DAsdk.IntfId(m.group(4))
          action = createAction(outputIntfs=[ outputIntf ])
          priority = 100
          entry = DAsdk.FlowEntry(name,
                                   match,
                                   action,
                                   priority)
          self.directFlowMgr_.flow_entry_set(entry)
       else:
          assert operation == "delete"
          self.directFlowMgr_.flow_entry_del(name)
예제 #2
0
    def _buildNexthopGroups(self):
        groups = self.config_.nexthop_groups
        for name, data in groups.iteritems():
            if data.type not in NEXTHOP_GROUP_TYPE:
                sys.stderr.write('Unknown nexthop group type="%s"' % data.type)
                continue
            t = data.type.lower()
            group = DAsdk.NexthopGroup(name, NEXTHOP_GROUP_TYPE.get(t))
            # Set common parameters
            for i, dst in enumerate(data.dst_ips):
                ip = get_ip_addr(dst)
                if ip is not None:
                    print 'Adding IP'
                    group.destination_ip_set(i, ip)

            if t == 'ipinip' or t == 'gre':
                if data.src_intf:
                    if self.intf_mgr.exists(DAsdk.IntfId(data.src_intf)):
                        group.source_intf_is(DAsdk.IntfId(data.src_intf))
                elif data.src_ips:
                    pass  # not yet supported
            elif t == 'mpls':
                sys.stderr.write('MPLS nexthop-groups are not yet supported\n')
            # Set the nexthop group
            print 'Setting nexthop group:', name
            self.nexthop_group_mgr.nexthop_group_set(group)
예제 #3
0
 def watch_policy(self):
     print 'Removing all watches for %s' % self.watches_
     for name in self.watches_:
         self.watch_policy_map(
             DAsdk.PolicyMapKey(name, DAsdk.POLICY_FEATURE_PBR), False)
     self.watches_ = frozenset(self.config_.policy.iterkeys())
     print 'Adding new watches for %s' % self.config_.policy.keys()
     for name in self.config_.policy:
         self.watch_policy_map(
             DAsdk.PolicyMapKey(name, DAsdk.POLICY_FEATURE_PBR), True)
예제 #4
0
 def _applyToInterfaces(self):
     interface_policy = self.config_.interface_policy
     for intf_name, data in interface_policy.iteritems():
         policy_map_key = DAsdk.PolicyMapKey(data.policy,
                                             DAsdk.POLICY_FEATURE_PBR)
         intf_id = DAsdk.IntfId(intf_name)
         if self.intf_mgr.exists(intf_id):
             print 'Interface %s exists, applying policy' % intf_id.to_string(
             )
             self.policy_map_mgr.policy_map_apply(policy_map_key, intf_id,
                                                  DAsdk.ACL_IN, True)
         else:
             print 'Interface %s does not exist' % intf_id.to_string()
     print 'Finished applying policy'
예제 #5
0
    def _buildClassMaps(self):
        classifiers = self.config_.classifiers
        for name, classifier in classifiers.iteritems():
            key = DAsdk.PolicyMapKey(name, DAsdk.POLICY_FEATURE_PBR)
            class_map = DAsdk.ClassMap(key)

            for rule_index, match in enumerate(classifier.matches):
                print 'Adding to class map:', name, 'seq:', str(rule_index +
                                                                1), match
                rule_key = DAsdk.AclKey(match.acl_name, DAsdk.ACL_TYPE_IPV4)
                rule = DAsdk.ClassMapRule(rule_key)
                # Set the action for the rule
                class_map.rule_set(rule_index + 1, rule)
            self.class_map_mgr.class_map_is(class_map)
            cm = self.class_map_mgr.class_map(key)
            print 'Set class map:', name, 'now with', len(cm.rules()), 'rules'
예제 #6
0
    def _buildPolicyMaps(self):
        policies = self.config_.policy
        for name, data in policies.iteritems():
            # add the class map
            rule_key = DAsdk.PolicyMapKey(data.classifier,
                                          DAsdk.POLICY_FEATURE_PBR)
            rule = DAsdk.PolicyMapRule(rule_key)

            for actionName in data.actions:
                # raises KeyError on uknown action names
                action = self.actions_[actionName]
                rule.action_set(action)
            key = DAsdk.PolicyMapKey(name, DAsdk.POLICY_FEATURE_PBR)
            policy_map = DAsdk.PolicyMap(key)
            policy_map.rule_set(1, rule)
            self.policy_map_mgr.policy_map_is(policy_map)
예제 #7
0
    def __init__(self, filename):
        self.agent_mgr = sdk.get_agent_mgr()
        self.tracer = DAsdk.Tracer("FileWatcher")
        DAsdk_utils.DASdkAgent.__init__(self)
        DAsdk.AgentHandler.__init__(self, self.agent_mgr)
        DAsdk.FdHandler.__init__(self)
        self.tracer.trace0("Watching %r" % filename)

        self.wm = pyinotify.WatchManager()
        # Pass the InotifyHandler's that wille be created a pointer to
        # ourselves by wrapping it in functools.partial:
        handler = functools.partial(InotifyHandler, parent=self)

        # pylint: disable-msg=E1101
        self.wm.watch_transient_file(filename, pyinotify.IN_MODIFY, handler)
        # pylint: enable-msg=E1101
        self.inotifier = pyinotify.AsyncNotifier(self.wm,
                                                 InotifyHandler(parent=self))
        # We coalesce events because some editors (or unix operations) cause
        # multiple changes on one save.
        self.inotifier.coalesce_events(True)

        # Now that we've set up our inotify watcher and notifier, grab
        # the underlying file descriptor and pass it to the SDK to be
        # watched. When the OS detects a change to the file, we'll
        self.inotify_fd = self.wm.get_fd()
        self.tracer.trace0("Watching inotify fd: %d" % self.inotify_fd)
        self.watch_readable(self.inotify_fd, True)
예제 #8
0
 def _buildActions(self):
     for name, action in self.config_.actions.iteritems():
         if action.type == 'drop':
             act = DAsdk.PolicyMapAction(DAsdk.POLICY_ACTION_DROP)
         elif action.type == 'nexthop_group' and action.nexthop_group:
             act = DAsdk.PolicyMapAction(DAsdk.POLICY_ACTION_NEXTHOP_GROUP)
             act.nexthop_group_name_is(action.nexthop_group)
         elif action.type == 'nexthop' and action.nexthops:
             act = DAsdk.PolicyMapAction(DAsdk.POLICY_ACTION_NEXTHOP)
             for nh in action.nexthops:
                 hop = get_ip_addr(nh)
                 if hop is not None:
                     act.nexthop_set(hop)
         else:
             raise ConfigError('Action type="%s" not supported' %
                               action.type)
         self.actions_[name] = act
예제 #9
0
def createMatch(inputIntfs=None,
                ethSrc=None,
                ethSrcMask="ff:ff:ff:ff:ff:ff",
                ethDst=None,
                ethDstMask="ff:ff:ff:ff:ff:ff",
                ethType=None,
                ipSrc=None,
                ipSrcMask="255.255.255.255",
                ipDst=None,
                ipDstMask="255.255.255.255"):
   match = DAsdk.FlowMatch()
   matchFieldSet = DAsdk.FlowMatchFieldSet()
   if inputIntfs is not None:
      # Until we have correct swig support for std::set,
      # need to add each interface individually
      matchFieldSet.input_intfs_is(True)
      match.input_intfs_is(tuple([intfId for intfId in inputIntfs]))
   if ethSrc is not None:
      matchFieldSet.eth_src_is(True)
      ethSrc = DAsdk.EthAddr(ethSrc)
      ethSrcMask = DAsdk.EthAddr(ethSrcMask)
      match.eth_src_is(ethSrc, ethSrcMask)
   if ethDst is not None:
      matchFieldSet.eth_dst_is(True)
      ethDst = DAsdk.EthAddr(ethDst)
      ethDstMask = DAsdk.EthAddr(ethDstMask)
      match.eth_dst_is(ethDst, ethDstMask)
   if ethType is not None:
      matchFieldSet.eth_type_is(True)
      match.eth_type_is(ethType)
   if ipSrc is not None:
      matchFieldSet.ip_src_is(True)
      ipSrc = DAsdk.IpAddr(ipSrc)
      ipSrcMask = DAsdk.IpAddr(ipSrcMask)
      match.ip_src_is(ipSrc, ipSrcMask)
   if ipDst is not None:
      matchFieldSet.ip_dst_is(True)
      ipDst = DAsdk.IpAddr(ipDst)
      ipDstMask = DAsdk.IpAddr(ipDstMask)
      match.ip_dst_is(ipDst, ipDstMask)
   match.match_field_set_is(matchFieldSet)
   return match
예제 #10
0
 def __init__(self, agentMgr, intfMgr, interfaceName):
     print "This program controls the admin enabled state of the given interface"
     print " - 'shutdown' will disable the interface"
     print " - any other text will enable the interface"
     print " - an empty line will quit this program"
     self.agentMgr_ = agentMgr
     self.intfMgr_ = intfMgr
     self.intfObj_ = DAsdk.IntfId(interfaceName)
     DAsdk.AgentHandler.__init__(self, agentMgr)
     DAsdk.FdHandler.__init__(self)
     self.eventCount = 0
예제 #11
0
   def __init__(self, intfMgr, agentMgr):
      DAsdk.AgentHandler.__init__(self, agentMgr)
      DAsdk.IntfHandler.__init__(self, intfMgr)
      self.tracer = DAsdk.Tracer("DASdkInterfaceMonitor")
      self.intfMgr_ = intfMgr
      self.agentMgr_ = agentMgr

      # Keep track of the total number of state changes. This number
      # gets reset whenever the agent is restarted.
      self.numIntfChanges_ = 0

      self.tracer.trace0("Constructed")
예제 #12
0
 def _buildPortSpec(self, portspec):
     op = portspec.get('op', 'eq').lower()  # default to port equals
     ports = portspec.get('ports', [])
     if op == 'eq':
         return DAsdk.AclPortSpec(DAsdk.ACL_RANGE_EQ, ports)
     elif op == 'neq':
         return DAsdk.AclPortSpec(DAsdk.ACL_RANGE_NEQ, ports)
     elif op == 'range':
         if len(ports) != 2:
             raise ConfigError('Must provide exactly two ports for "range"')
         return DAsdk.AclPortSpec(DAsdk.ACL_RANGE_BETWEEN, ports)
     elif op == 'gt':
         if len(ports) != 1:
             raise ConfigError('Must provide only one port for "gt"')
         return DAsdk.AclPortSpec(DAsdk.ACL_RANGE_GT, ports)
     elif op == 'lt':
         if len(ports) != 1:
             raise ConfigError('Must provide only one port for "lt"')
         return DAsdk.AclPortSpec(DAsdk.ACL_RANGE_LT, ports)
     else:
         raise ConfigError('Unknown port match operation "%s"' % op)
예제 #13
0
def createAction(outputIntfs=None,
                 ethSrc=None,
                 ethDst=None,
                 ipSrc=None,
                 ipDst=None):
   action = DAsdk.FlowAction()
   actionSet = DAsdk.FlowActionSet()
   if outputIntfs is not None:
      # Until we have correct swig support for std::set,
      # need to add each interface individually
      actionSet.set_output_intfs_is(True)
      action.output_intfs_is(tuple([intfId for intfId in outputIntfs]))
   if ethSrc is not None:
      actionSet.set_eth_src_is(True)
      newEthSrc = DAsdk.EthAddr(ethSrc)
      action.eth_src_is(newEthSrc)
   if ethDst is not None:
      actionSet.set_eth_dst_is(True)
      newEthDst = DAsdk.EthAddr(ethDst)
      action.eth_dst_is(newEthDst)
   if ipSrc is not None:
      actionSet.set_ip_src_is(True)
      newIpSrc = DAsdk.IpAddr(ipSrc)
      action.ip_src_is(newIpSrc)
   if ipDst is not None:
      actionSet.set_ip_dst_is(True)
      newIpDst = DAsdk.IpAddr(ipDst)
      action.ip_dst_is(newIpDst)
   action.action_set_is(actionSet)
   return action
예제 #14
0
def main():
    # Because we use `print' and we want our stuff to show up in the
    # agent logs immediately.
    os.environ['PYTHONUNBUFFERED'] = '1'  # TODO: Use tracing instead.
    # Config file path has to be provided by the environment variable
    filename = os.environ.get('POLICY_ROUTER_CONFIG')

    # Obtain a reference to the DA SDK
    sdk = DAsdk.Sdk()
    # Instantiate the policy router application
    _ = PolicyHandler(sdk, filename)
    # Run the agent until terminated by a signal
    sdk.main_loop(['PolicyRouter'])
예제 #15
0
 def __init__(self, sdk, config_file, policy_handler, poll_interval=0.5):
     self.config_file_ = config_file
     self.sdk_ = sdk
     self.policy_handler_ = policy_handler
     self.poll_interval_ = poll_interval
     self.wm_ = pyinotify.WatchManager()
     mask = pyinotify.IN_MODIFY | pyinotify.IN_CREATE | pyinotify.IN_DELETE
     handler = functools.partial(InotifyHandler, handler=policy_handler)
     # Allow coalescing, so that delete/recreate (as opposed to modify) doesn't
     # cause us to delete the policy.
     self.notifier_ = pyinotify.Notifier(self.wm_, handler, timeout=10)
     self.notifier_.coalesce_events()
     self.watch_ = self.wm_.watch_transient_file(self.config_file_, mask,
                                                 handler)
     DAsdk.TimeoutHandler.__init__(self, self.sdk_.get_timeout_mgr())
     self.timeout_time_is(DAsdk.now())
예제 #16
0
    def _buildAcls(self):
        for aclname, aclrules in self.config.match.iteritems():
            key = DAsdk.AclKey(aclname, DAsdk.ACL_TYPE_IPV4)

            # todo support ipv6 also
            for i, rule in enumerate(aclrules):
                aclRule = DAsdk.AclRuleIp()

                if rule.proto:
                    pr = PROTOCOLS.get(rule.proto.lower())
                    if pr:
                        aclRule.ip_protocol_is(pr)
                    else:
                        sys.stderr.write('Invalid protocol name "%s"',
                                         rule.proto)

                if rule.src_ip:
                    try:
                        srcPfx = DAsdk.IpPrefix(rule.src_ip)
                        addr = DAsdk.IpAddrMask(srcPfx.network(),
                                                srcPfx.prefix_length())
                        aclRule.source_addr_is(addr)
                    except DAsdk.Error:
                        sys.stderr.write('bad IP address: %s\n', rule.src_ip)
                        continue

                if rule.dst_ip:
                    try:
                        dstPfx = DAsdk.IpPrefix(rule.dst_ip)
                        addr = DAsdk.IpAddrMask(dstPfx.network(),
                                                dstPfx.prefix_length())
                        aclRule.destination_addr_is(addr)
                    except DAsdk.Error:
                        sys.stderr.write('bad IP address: %s\n', rule.dst_ip)
                        continue

                if rule.sport:
                    try:
                        spec = self._buildPortSpec(rule.sport)
                    except ConfigError as e:
                        sys.stderr.write('Invalid port spec %r: %s\n', spec, e)
                    else:
                        aclRule.source_port_is(spec)

                if rule.dport:
                    try:
                        spec = self._buildPortSpec(rule.dport)
                    except ConfigError as e:
                        sys.stderr.write('Invalid port spec %r: %s\n', spec, e)
                    else:
                        aclRule.destination_port_is(spec)

                self.acl_mgr.acl_rule_set(key, i, aclRule)
        self.acl_mgr.acl_commit()
예제 #17
0
   def on_initialized(self):
      # Resynchronize initial flows
      # Uncomment once we've added hitless resync support to the API:
      # self.directFlowMgr_.resync_init()
      # Add default flow entry. In this case, drop all IPv4 traffic.
      defaultEntry = DAsdk.FlowEntry("DefaultFlow",
                                      createMatch(ipDst="0.0.0.0",
                                                  ipDstMask="0.0.0.0"),
                                      createAction(outputIntfs=[]),
                                      0)
      self.directFlowMgr_.flow_entry_set(defaultEntry)
      # Uncomment once we've added hitless resync support to the API:
      # self.directFlowMgr_.resync_complete()

      # Now start accepting input on stdin
      self.watch_all_flows(True)
      self.watch_readable(sys.stdin.fileno(), True)
예제 #18
0
def get_ip_addr(ip_addr):
    try:
        return DAsdk.IpAddr(ip_addr)
    except DAsdk.Error as e:
        sys.stderr.write('Invalid IP address: %s (%s)' % (ip_addr, e))
예제 #19
0
import DAsdk
import sys


class MyIntfHandler( DAsdk.AgentHandler, DAsdk.IntfHandler ):
   def __init__( self, intfMgr, agentMgr ):
      DAsdk.AgentHandler.__init__( self, agentMgr )
      DAsdk.IntfHandler.__init__( self, intfMgr )  # pylint: disable-msg=W0233
      self.intfMgr_ = intfMgr
      self.numIntfChanges_ = 0
      print "Constructed"

   # Callback provided by AgentHandler when all state is synchronized
   def on_initialized( self ):
      print "We are initialized!"
      self.watch_all_intfs( True )  # pylint: disable-msg=E1101

   # Callback provided by IntfHandler when an interface's configuration changes
   def on_oper_status( self, intfId, operState ):
      intfState = 'up' if operState == DAsdk.INTF_OPER_UP else 'down'
      print "The state of", intfId.to_string(), "is now", intfState
      self.numIntfChanges_ += 1
      print "   We have seen", self.numIntfChanges_, "state changes"
      self.intfMgr_.description_is(intfId,
                                   "Changed state [%d]" % self.numIntfChanges_)


sdk = DAsdk.Sdk()
mta = MyIntfHandler( sdk.get_intf_mgr(), sdk.get_agent_mgr() )
sdk.main_loop( sys.argv )
예제 #20
0
 def on_timeout(self):
     self.poll()
     self.timeout_time_is(DAsdk.now() + self.poll_interval_)
예제 #21
0
def main(args):
   sdk = DAsdk.Sdk("DirectFlowProgrammer")
   programmer = DirectFlowProgrammer(sdk.get_agent_mgr(), sdk.get_directflow_mgr())
   sdk.main_loop(sys.argv)
   print "Saw %d flow status changes" % programmer.changes
예제 #22
0
      name = self.agentMgr.agent_option("name")
      if not name:
         # No name initially set
         self.agentMgr.status_set("greeting", "Welcome! What is your name?")
      else:
         # Handle the initial state
         self.on_agent_option("name", name)

   def on_agent_option(self, optionName, value):
      if optionName == "name":
         if not value:
            self.tracer.trace3("Name deleted")
            self.agentMgr.status_set("greeting", "Goodbye!")
         else:
            # Time for some social networking!
            self.tracer.trace3("Saying hi to %s" % value)
            self.agentMgr.status_set("greeting", "Hello %s!" % value)

   def on_agent_enabled(self, enabled):
      if not enabled:
         self.tracer.trace0("Shutting down")
         self.agentMgr.status_set("greeting", "Adios!")
         self.agentMgr.agent_shutdown_complete_is(True)

if __name__ == "__main__":
   sdk_ = DAsdk.Sdk()
   # Assign the agent instance to a variable so it remains in scope and
   # is not deleted:
   _ = HelloWorldAgent(sdk_)
   sdk_.main_loop(sys.argv)
예제 #23
0
 def __init__(self, sdk):
    self.agentMgr = sdk.get_agent_mgr()
    self.tracer = DAsdk.Tracer("HelloWorldPythonAgent")
    DAsdk.AgentHandler.__init__(self, self.agentMgr)
    self.tracer.trace0("Python agent constructed")
예제 #24
0
def main(args):
    sdk = DAsdk.Sdk()
    testAgent = MyTestAgent(sdk.get_agent_mgr(), sdk.get_intf_mgr(),
                            "Ethernet1")
    sdk.main_loop(args)
    print "Handled %d events" % testAgent.eventCount