<s> """<STR_LIT>""" <EOL> import logging <EOL> import six <EOL> import time <EOL> import random <EOL> from ryu . base import app_manager <EOL> from ryu . controller import event <EOL> from ryu . controller import ofp_event <EOL> from ryu . controller . handler import CONFIG_DISPATCHER , MAIN_DISPATCHER <EOL> from ryu . controller . handler import set_ev_cls <EOL> from ryu . exception import RyuException <EOL> from ryu . ofproto . ether import ETH_TYPE_IP , ETH_TYPE_ARP <EOL> from ryu . ofproto import ofproto_v1_3 <EOL> from ryu . ofproto import inet <EOL> from ryu . lib import ofctl_v1_3 <EOL> from ryu . lib import hub <EOL> from ryu . lib . packet import packet <EOL> from ryu . lib . packet import ethernet <EOL> from ryu . lib . packet import ipv4 <EOL> from ryu . lib . packet import udp <EOL> from ryu . lib . packet import bfd <EOL> from ryu . lib . packet import arp <EOL> from ryu . lib . packet . arp import ARP_REQUEST , ARP_REPLY <EOL> LOG = logging . getLogger ( __name__ ) <EOL> UINT16_MAX = ( <NUM_LIT:1> << <NUM_LIT:16> ) - <NUM_LIT:1> <EOL> UINT32_MAX = ( <NUM_LIT:1> << <NUM_LIT:32> ) - <NUM_LIT:1> <EOL> BFD_CONTROL_UDP_PORT = <NUM_LIT> <EOL> BFD_ECHO_UDP_PORT = <NUM_LIT> <EOL> class BFDSession ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , app , my_discr , dpid , ofport , <EOL> src_mac , src_ip , src_port , <EOL> dst_mac = "<STR_LIT>" , dst_ip = "<STR_LIT>" , <EOL> detect_mult = <NUM_LIT:3> , <EOL> desired_min_tx_interval = <NUM_LIT> , <EOL> required_min_rx_interval = <NUM_LIT> , <EOL> auth_type = <NUM_LIT:0> , auth_keys = None ) : <EOL> """<STR_LIT>""" <EOL> auth_keys = auth_keys if auth_keys else { } <EOL> assert not ( auth_type and len ( auth_keys ) == <NUM_LIT:0> ) <EOL> self . app = app <EOL> self . _session_state = bfd . BFD_STATE_DOWN <EOL> self . _remote_session_state = bfd . BFD_STATE_DOWN <EOL> self . _local_discr = my_discr <EOL> self . _remote_discr = <NUM_LIT:0> <EOL> self . _local_diag = <NUM_LIT:0> <EOL> self . _desired_min_tx_interval = <NUM_LIT> <EOL> self . _required_min_rx_interval = required_min_rx_interval <EOL> self . _remote_min_rx_interval = - <NUM_LIT:1> <EOL> self . _demand_mode = <NUM_LIT:0> <EOL> self . _remote_demand_mode = <NUM_LIT:0> <EOL> self . _detect_mult = detect_mult <EOL> self . _auth_type = auth_type <EOL> self . _auth_keys = auth_keys <EOL> if self . _auth_type in [ bfd . BFD_AUTH_KEYED_MD5 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_MD5 , <EOL> bfd . BFD_AUTH_KEYED_SHA1 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_SHA1 ] : <EOL> self . _rcv_auth_seq = <NUM_LIT:0> <EOL> self . _xmit_auth_seq = random . randint ( <NUM_LIT:0> , UINT32_MAX ) <EOL> self . _auth_seq_known = <NUM_LIT:0> <EOL> self . _cfg_desired_min_tx_interval = desired_min_tx_interval <EOL> self . _cfg_required_min_echo_rx_interval = <NUM_LIT:0> <EOL> self . _active_role = True <EOL> self . _detect_time = <NUM_LIT:0> <EOL> self . _xmit_period = None <EOL> self . _update_xmit_period ( ) <EOL> self . _is_polling = True <EOL> self . _pending_final = False <EOL> self . _enable_send = True <EOL> self . _lock = None <EOL> self . src_mac = src_mac <EOL> self . dst_mac = dst_mac <EOL> self . src_ip = src_ip <EOL> self . dst_ip = dst_ip <EOL> self . ipv4_id = random . randint ( <NUM_LIT:0> , UINT16_MAX ) <EOL> self . src_port = src_port <EOL> self . dst_port = BFD_CONTROL_UDP_PORT <EOL> if dst_mac == "<STR_LIT>" or dst_ip == "<STR_LIT>" : <EOL> self . _remote_addr_config = False <EOL> else : <EOL> self . _remote_addr_config = True <EOL> self . dpid = dpid <EOL> self . datapath = None <EOL> self . ofport = ofport <EOL> hub . spawn ( self . _send_loop ) <EOL> LOG . info ( "<STR_LIT>" , <EOL> hex ( self . _local_discr ) ) <EOL> @ property <EOL> def my_discr ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _local_discr <EOL> @ property <EOL> def your_discr ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _remote_discr <EOL> def set_remote_addr ( self , dst_mac , dst_ip ) : <EOL> """<STR_LIT>""" <EOL> self . dst_mac = dst_mac <EOL> self . dst_ip = dst_ip <EOL> if not ( dst_mac == "<STR_LIT>" or dst_ip == "<STR_LIT>" ) : <EOL> self . _remote_addr_config = True <EOL> LOG . info ( "<STR_LIT>" , <EOL> hex ( self . _local_discr ) , self . dst_ip , self . dst_mac ) <EOL> def recv ( self , bfd_pkt ) : <EOL> """<STR_LIT>""" <EOL> LOG . debug ( "<STR_LIT>" , <EOL> hex ( self . _local_discr ) , six . binary_type ( bfd_pkt ) ) <EOL> self . _remote_discr = bfd_pkt . my_discr <EOL> self . _remote_state = bfd_pkt . state <EOL> self . _remote_demand_mode = bfd_pkt . flags & bfd . BFD_FLAG_DEMAND <EOL> if self . _remote_min_rx_interval != bfd_pkt . required_min_rx_interval : <EOL> self . _remote_min_rx_interval = bfd_pkt . required_min_rx_interval <EOL> self . _update_xmit_period ( ) <EOL> if bfd_pkt . flags & bfd . BFD_FLAG_FINAL and self . _is_polling : <EOL> self . _is_polling = False <EOL> if self . _session_state == bfd . BFD_STATE_ADMIN_DOWN : <EOL> return <EOL> if bfd_pkt . state == bfd . BFD_STATE_ADMIN_DOWN : <EOL> if self . _session_state != bfd . BFD_STATE_DOWN : <EOL> self . _set_state ( bfd . BFD_STATE_DOWN , <EOL> bfd . BFD_DIAG_NEIG_SIG_SESS_DOWN ) <EOL> else : <EOL> if self . _session_state == bfd . BFD_STATE_DOWN : <EOL> if bfd_pkt . state == bfd . BFD_STATE_DOWN : <EOL> self . _set_state ( bfd . BFD_STATE_INIT ) <EOL> elif bfd_pkt . state == bfd . BFD_STATE_INIT : <EOL> self . _set_state ( bfd . BFD_STATE_UP ) <EOL> elif self . _session_state == bfd . BFD_STATE_INIT : <EOL> if bfd_pkt . state in [ bfd . BFD_STATE_INIT , bfd . BFD_STATE_UP ] : <EOL> self . _set_state ( bfd . BFD_STATE_UP ) <EOL> else : <EOL> if bfd_pkt . state == bfd . BFD_STATE_DOWN : <EOL> self . _set_state ( bfd . BFD_STATE_DOWN , <EOL> bfd . BFD_DIAG_NEIG_SIG_SESS_DOWN ) <EOL> if self . _remote_demand_mode and self . _session_state == bfd . BFD_STATE_UP and self . _remote_session_state == bfd . BFD_STATE_UP : <EOL> self . _enable_send = False <EOL> if not self . _remote_demand_mode or self . _session_state != bfd . BFD_STATE_UP or self . _remote_session_state != bfd . BFD_STATE_UP : <EOL> if not self . _enable_send : <EOL> self . _enable_send = True <EOL> hub . spawn ( self . _send_loop ) <EOL> if self . _detect_time == <NUM_LIT:0> : <EOL> self . _detect_time = bfd_pkt . desired_min_tx_interval * bfd_pkt . detect_mult / <NUM_LIT> <EOL> hub . spawn ( self . _recv_timeout_loop ) <EOL> if bfd_pkt . flags & bfd . BFD_FLAG_POLL : <EOL> self . _pending_final = True <EOL> self . _detect_time = bfd_pkt . desired_min_tx_interval * bfd_pkt . detect_mult / <NUM_LIT> <EOL> if self . _auth_type in [ bfd . BFD_AUTH_KEYED_MD5 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_MD5 , <EOL> bfd . BFD_AUTH_KEYED_SHA1 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_SHA1 ] : <EOL> self . _rcv_auth_seq = bfd_pkt . auth_cls . seq <EOL> self . _auth_seq_known = <NUM_LIT:1> <EOL> if self . _lock is not None : <EOL> self . _lock . set ( ) <EOL> def _set_state ( self , new_state , diag = None ) : <EOL> """<STR_LIT>""" <EOL> old_state = self . _session_state <EOL> LOG . info ( "<STR_LIT>" , <EOL> hex ( self . _local_discr ) , <EOL> bfd . BFD_STATE_NAME [ old_state ] , <EOL> bfd . BFD_STATE_NAME [ new_state ] ) <EOL> self . _session_state = new_state <EOL> if new_state == bfd . BFD_STATE_DOWN : <EOL> if diag is not None : <EOL> self . _local_diag = diag <EOL> self . _desired_min_tx_interval = <NUM_LIT> <EOL> self . _is_polling = True <EOL> self . _update_xmit_period ( ) <EOL> elif new_state == bfd . BFD_STATE_UP : <EOL> self . _desired_min_tx_interval = self . _cfg_desired_min_tx_interval <EOL> self . _is_polling = True <EOL> self . _update_xmit_period ( ) <EOL> self . app . send_event_to_observers ( <EOL> EventBFDSessionStateChanged ( self , old_state , new_state ) ) <EOL> def _recv_timeout_loop ( self ) : <EOL> """<STR_LIT>""" <EOL> while self . _detect_time : <EOL> last_wait = time . time ( ) <EOL> self . _lock = hub . Event ( ) <EOL> self . _lock . wait ( timeout = self . _detect_time ) <EOL> if self . _lock . is_set ( ) : <EOL> if getattr ( self , "<STR_LIT>" , <NUM_LIT:0> ) : <EOL> if last_wait > time . time ( ) + <NUM_LIT:2> * self . _detect_time : <EOL> self . _auth_seq_known = <NUM_LIT:0> <EOL> else : <EOL> LOG . info ( "<STR_LIT>" , <EOL> hex ( self . _local_discr ) ) <EOL> if self . _session_state not in [ bfd . BFD_STATE_DOWN , <EOL> bfd . BFD_STATE_ADMIN_DOWN ] : <EOL> self . _set_state ( bfd . BFD_STATE_DOWN , <EOL> bfd . BFD_DIAG_CTRL_DETECT_TIME_EXPIRED ) <EOL> if getattr ( self , "<STR_LIT>" , <NUM_LIT:0> ) : <EOL> self . _auth_seq_known = <NUM_LIT:0> <EOL> def _update_xmit_period ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . _desired_min_tx_interval > self . _remote_min_rx_interval : <EOL> xmit_period = self . _desired_min_tx_interval <EOL> else : <EOL> xmit_period = self . _remote_min_rx_interval <EOL> if self . _detect_mult == <NUM_LIT:1> : <EOL> xmit_period *= random . randint ( <NUM_LIT> , <NUM_LIT> ) / <NUM_LIT> <EOL> else : <EOL> xmit_period *= random . randint ( <NUM_LIT> , <NUM_LIT:100> ) / <NUM_LIT> <EOL> self . _xmit_period = xmit_period / <NUM_LIT> <EOL> LOG . info ( "<STR_LIT>" , <EOL> hex ( self . _local_discr ) , self . _xmit_period ) <EOL> def _send_loop ( self ) : <EOL> """<STR_LIT>""" <EOL> while self . _enable_send : <EOL> hub . sleep ( self . _xmit_period ) <EOL> if self . _remote_discr == <NUM_LIT:0> and not self . _active_role : <EOL> continue <EOL> if self . _remote_min_rx_interval == <NUM_LIT:0> : <EOL> continue <EOL> if self . _remote_demand_mode and self . _session_state == bfd . BFD_STATE_UP and self . _remote_session_state == bfd . BFD_STATE_UP and not self . _is_polling : <EOL> continue <EOL> self . _send ( ) <EOL> def _send ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . datapath is None : <EOL> return <EOL> flags = <NUM_LIT:0> <EOL> if self . _pending_final : <EOL> flags |= bfd . BFD_FLAG_FINAL <EOL> self . _pending_final = False <EOL> self . _is_polling = False <EOL> if self . _is_polling : <EOL> flags |= bfd . BFD_FLAG_POLL <EOL> auth_cls = None <EOL> if self . _auth_type : <EOL> auth_key_id = list ( self . _auth_keys . keys ( ) ) [ <EOL> random . randint ( <NUM_LIT:0> , len ( list ( self . _auth_keys . keys ( ) ) ) - <NUM_LIT:1> ) ] <EOL> auth_key = self . _auth_keys [ auth_key_id ] <EOL> if self . _auth_type == bfd . BFD_AUTH_SIMPLE_PASS : <EOL> auth_cls = bfd . SimplePassword ( auth_key_id = auth_key_id , <EOL> password = auth_key ) <EOL> if self . _auth_type in [ bfd . BFD_AUTH_KEYED_MD5 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_MD5 , <EOL> bfd . BFD_AUTH_KEYED_SHA1 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_SHA1 ] : <EOL> if self . _auth_type in [ bfd . BFD_AUTH_KEYED_MD5 , <EOL> bfd . BFD_AUTH_KEYED_SHA1 ] : <EOL> if random . randint ( <NUM_LIT:0> , <NUM_LIT:1> ) : <EOL> self . _xmit_auth_seq = ( self . _xmit_auth_seq + <NUM_LIT:1> ) & UINT32_MAX <EOL> else : <EOL> self . _xmit_auth_seq = ( self . _xmit_auth_seq + <NUM_LIT:1> ) & UINT32_MAX <EOL> auth_cls = bfd . bfd . _auth_parsers [ self . _auth_type ] ( <EOL> auth_key_id = auth_key_id , <EOL> seq = self . _xmit_auth_seq , <EOL> auth_key = auth_key ) <EOL> if auth_cls is not None : <EOL> flags |= bfd . BFD_FLAG_AUTH_PRESENT <EOL> if self . _demand_mode and self . _session_state == bfd . BFD_STATE_UP and self . _remote_session_state == bfd . BFD_STATE_UP : <EOL> flags |= bfd . BFD_FLAG_DEMAND <EOL> ver = <NUM_LIT:1> <EOL> diag = self . _local_diag <EOL> state = self . _session_state <EOL> detect_mult = self . _detect_mult <EOL> my_discr = self . _local_discr <EOL> your_discr = self . _remote_discr <EOL> desired_min_tx_interval = self . _desired_min_tx_interval <EOL> required_min_rx_interval = self . _required_min_rx_interval <EOL> required_min_echo_rx_interval = self . _cfg_required_min_echo_rx_interval <EOL> src_mac = self . src_mac <EOL> dst_mac = self . dst_mac <EOL> src_ip = self . src_ip <EOL> dst_ip = self . dst_ip <EOL> self . ipv4_id = ( self . ipv4_id + <NUM_LIT:1> ) & UINT16_MAX <EOL> ipv4_id = self . ipv4_id <EOL> src_port = self . src_port <EOL> dst_port = self . dst_port <EOL> data = BFDPacket . bfd_packet ( <EOL> src_mac = src_mac , dst_mac = dst_mac , <EOL> src_ip = src_ip , dst_ip = dst_ip , ipv4_id = ipv4_id , <EOL> src_port = src_port , dst_port = dst_port , <EOL> diag = diag , state = state , flags = flags , detect_mult = detect_mult , <EOL> my_discr = my_discr , your_discr = your_discr , <EOL> desired_min_tx_interval = desired_min_tx_interval , <EOL> required_min_rx_interval = required_min_rx_interval , <EOL> required_min_echo_rx_interval = required_min_echo_rx_interval , <EOL> auth_cls = auth_cls ) <EOL> datapath = self . datapath <EOL> ofproto = datapath . ofproto <EOL> parser = datapath . ofproto_parser <EOL> actions = [ parser . OFPActionOutput ( self . ofport ) ] <EOL> out = parser . OFPPacketOut ( datapath = datapath , <EOL> buffer_id = ofproto . OFP_NO_BUFFER , <EOL> in_port = ofproto . OFPP_CONTROLLER , <EOL> actions = actions , <EOL> data = data ) <EOL> datapath . send_msg ( out ) <EOL> LOG . debug ( "<STR_LIT>" , hex ( self . _local_discr ) ) <EOL> class BFDPacket ( object ) : <EOL> """<STR_LIT>""" <EOL> class BFDUnknownFormat ( RyuException ) : <EOL> message = '<STR_LIT>' <EOL> @ staticmethod <EOL> def bfd_packet ( src_mac , dst_mac , src_ip , dst_ip , ipv4_id , <EOL> src_port , dst_port , <EOL> diag = <NUM_LIT:0> , state = <NUM_LIT:0> , flags = <NUM_LIT:0> , detect_mult = <NUM_LIT:0> , <EOL> my_discr = <NUM_LIT:0> , your_discr = <NUM_LIT:0> , desired_min_tx_interval = <NUM_LIT:0> , <EOL> required_min_rx_interval = <NUM_LIT:0> , <EOL> required_min_echo_rx_interval = <NUM_LIT:0> , <EOL> auth_cls = None ) : <EOL> """<STR_LIT>""" <EOL> pkt = packet . Packet ( ) <EOL> eth_pkt = ethernet . ethernet ( dst_mac , src_mac , ETH_TYPE_IP ) <EOL> pkt . add_protocol ( eth_pkt ) <EOL> ipv4_pkt = ipv4 . ipv4 ( proto = inet . IPPROTO_UDP , src = src_ip , dst = dst_ip , <EOL> tos = <NUM_LIT> , identification = ipv4_id , ttl = <NUM_LIT:255> ) <EOL> pkt . add_protocol ( ipv4_pkt ) <EOL> udp_pkt = udp . udp ( src_port = src_port , dst_port = dst_port ) <EOL> pkt . add_protocol ( udp_pkt ) <EOL> bfd_pkt = bfd . bfd ( <EOL> ver = <NUM_LIT:1> , diag = diag , state = state , flags = flags , <EOL> detect_mult = detect_mult , <EOL> my_discr = my_discr , your_discr = your_discr , <EOL> desired_min_tx_interval = desired_min_tx_interval , <EOL> required_min_rx_interval = required_min_rx_interval , <EOL> required_min_echo_rx_interval = required_min_echo_rx_interval , <EOL> auth_cls = auth_cls ) <EOL> pkt . add_protocol ( bfd_pkt ) <EOL> pkt . serialize ( ) <EOL> return pkt . data <EOL> @ staticmethod <EOL> def bfd_parse ( data ) : <EOL> """<STR_LIT>""" <EOL> pkt = packet . Packet ( data ) <EOL> i = iter ( pkt ) <EOL> eth_pkt = next ( i ) <EOL> assert type ( eth_pkt ) == ethernet . ethernet <EOL> ipv4_pkt = next ( i ) <EOL> assert type ( ipv4_pkt ) == ipv4 . ipv4 <EOL> udp_pkt = i . next ( ) <EOL> assert type ( udp_pkt ) == udp . udp <EOL> udp_payload = next ( i ) <EOL> return bfd . bfd . parser ( udp_payload ) [ <NUM_LIT:0> ] <EOL> class ARPPacket ( object ) : <EOL> """<STR_LIT>""" <EOL> class ARPUnknownFormat ( RyuException ) : <EOL> message = '<STR_LIT>' <EOL> @ staticmethod <EOL> def arp_packet ( opcode , src_mac , src_ip , dst_mac , dst_ip ) : <EOL> """<STR_LIT>""" <EOL> pkt = packet . Packet ( ) <EOL> eth_pkt = ethernet . ethernet ( dst_mac , src_mac , ETH_TYPE_ARP ) <EOL> pkt . add_protocol ( eth_pkt ) <EOL> arp_pkt = arp . arp_ip ( opcode , src_mac , src_ip , dst_mac , dst_ip ) <EOL> pkt . add_protocol ( arp_pkt ) <EOL> pkt . serialize ( ) <EOL> return pkt . data <EOL> @ staticmethod <EOL> def arp_parse ( data ) : <EOL> """<STR_LIT>""" <EOL> pkt = packet . Packet ( data ) <EOL> i = iter ( pkt ) <EOL> eth_pkt = next ( i ) <EOL> assert type ( eth_pkt ) == ethernet . ethernet <EOL> arp_pkt = next ( i ) <EOL> if type ( arp_pkt ) != arp . arp : <EOL> raise ARPPacket . ARPUnknownFormat ( ) <EOL> if arp_pkt . opcode not in ( ARP_REQUEST , ARP_REPLY ) : <EOL> raise ARPPacket . ARPUnknownFormat ( <EOL> msg = '<STR_LIT>' % arp_pkt . opcode ) <EOL> if arp_pkt . proto != ETH_TYPE_IP : <EOL> raise ARPPacket . ARPUnknownFormat ( <EOL> msg = '<STR_LIT>' % arp_pkt . proto ) <EOL> return arp_pkt <EOL> class EventBFDSessionStateChanged ( event . EventBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , session , old_state , new_state ) : <EOL> super ( EventBFDSessionStateChanged , self ) . __init__ ( ) <EOL> self . session = session <EOL> self . old_state = old_state <EOL> self . new_state = new_state <EOL> class BFDLib ( app_manager . RyuApp ) : <EOL> """<STR_LIT>""" <EOL> OFP_VERSIONS = [ ofproto_v1_3 . OFP_VERSION ] <EOL> _EVENTS = [ EventBFDSessionStateChanged ] <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( BFDLib , self ) . __init__ ( * args , ** kwargs ) <EOL> self . session = { } <EOL> def close ( self ) : <EOL> pass <EOL> @ set_ev_cls ( ofp_event . EventOFPSwitchFeatures , CONFIG_DISPATCHER ) <EOL> def switch_features_handler ( self , ev ) : <EOL> datapath = ev . msg . datapath <EOL> ofproto = datapath . ofproto <EOL> parser = datapath . ofproto_parser <EOL> for s in self . session . values ( ) : <EOL> if s . dpid == datapath . id : <EOL> s . datapath = datapath <EOL> match = parser . OFPMatch ( eth_type = ETH_TYPE_ARP ) <EOL> actions = [ parser . OFPActionOutput ( ofproto . OFPP_CONTROLLER , <EOL> ofproto . OFPCML_NO_BUFFER ) ] <EOL> self . add_flow ( datapath , <NUM_LIT> , match , actions ) <EOL> match = parser . OFPMatch ( eth_type = ETH_TYPE_IP , <EOL> ip_proto = inet . IPPROTO_UDP , <EOL> udp_dst = <NUM_LIT> ) <EOL> actions = [ parser . OFPActionOutput ( ofproto . OFPP_CONTROLLER , <EOL> ofproto . OFPCML_NO_BUFFER ) ] <EOL> self . add_flow ( datapath , <NUM_LIT> , match , actions ) <EOL> def add_flow ( self , datapath , priority , match , actions ) : <EOL> ofproto = datapath . ofproto <EOL> parser = datapath . ofproto_parser <EOL> inst = [ parser . OFPInstructionActions ( ofproto . OFPIT_APPLY_ACTIONS , <EOL> actions ) ] <EOL> mod = parser . OFPFlowMod ( datapath = datapath , priority = priority , <EOL> match = match , instructions = inst ) <EOL> datapath . send_msg ( mod ) <EOL> @ set_ev_cls ( ofp_event . EventOFPPacketIn , MAIN_DISPATCHER ) <EOL> def _packet_in_handler ( self , ev ) : <EOL> msg = ev . msg <EOL> datapath = msg . datapath <EOL> ofproto = datapath . ofproto <EOL> parser = datapath . ofproto_parser <EOL> in_port = msg . match [ '<STR_LIT>' ] <EOL> pkt = packet . Packet ( msg . data ) <EOL> if arp . arp in pkt : <EOL> arp_pkt = ARPPacket . arp_parse ( msg . data ) <EOL> if arp_pkt . opcode == ARP_REQUEST : <EOL> for s in self . session . values ( ) : <EOL> if s . dpid == datapath . id and s . ofport == in_port and s . src_ip == arp_pkt . dst_ip : <EOL> ans = ARPPacket . arp_packet ( <EOL> ARP_REPLY , <EOL> s . src_mac , s . src_ip , <EOL> arp_pkt . src_mac , arp_pkt . src_ip ) <EOL> actions = [ parser . OFPActionOutput ( in_port ) ] <EOL> out = parser . OFPPacketOut ( <EOL> datapath = datapath , <EOL> buffer_id = ofproto . OFP_NO_BUFFER , <EOL> in_port = ofproto . OFPP_CONTROLLER , <EOL> actions = actions , data = ans ) <EOL> datapath . send_msg ( out ) <EOL> return <EOL> return <EOL> if ipv4 . ipv4 not in pkt or udp . udp not in pkt : <EOL> return <EOL> udp_hdr = pkt . get_protocols ( udp . udp ) [ <NUM_LIT:0> ] <EOL> if udp_hdr . dst_port != BFD_CONTROL_UDP_PORT : <EOL> return <EOL> self . recv_bfd_pkt ( datapath , in_port , msg . data ) <EOL> def add_bfd_session ( self , dpid , ofport , src_mac , src_ip , <EOL> dst_mac = "<STR_LIT>" , dst_ip = "<STR_LIT>" , <EOL> auth_type = <NUM_LIT:0> , auth_keys = None ) : <EOL> """<STR_LIT>""" <EOL> auth_keys = auth_keys if auth_keys else { } <EOL> while True : <EOL> my_discr = random . randint ( <NUM_LIT:1> , UINT32_MAX ) <EOL> src_port = random . randint ( <NUM_LIT> , <NUM_LIT> ) <EOL> if my_discr in self . session : <EOL> continue <EOL> unique_flag = True <EOL> for s in self . session . values ( ) : <EOL> if s . your_discr == my_discr or s . src_port == src_port : <EOL> unique_flag = False <EOL> break <EOL> if unique_flag : <EOL> break <EOL> sess = BFDSession ( app = self , my_discr = my_discr , <EOL> dpid = dpid , ofport = ofport , <EOL> src_mac = src_mac , src_ip = src_ip , src_port = src_port , <EOL> dst_mac = dst_mac , dst_ip = dst_ip , <EOL> auth_type = auth_type , auth_keys = auth_keys ) <EOL> self . session [ my_discr ] = sess <EOL> return my_discr <EOL> def recv_bfd_pkt ( self , datapath , in_port , data ) : <EOL> pkt = packet . Packet ( data ) <EOL> eth = pkt . get_protocols ( ethernet . ethernet ) [ <NUM_LIT:0> ] <EOL> if eth . ethertype != ETH_TYPE_IP : <EOL> return <EOL> ip_pkt = pkt . get_protocols ( ipv4 . ipv4 ) [ <NUM_LIT:0> ] <EOL> if ip_pkt . ttl != <NUM_LIT:255> : <EOL> return <EOL> bfd_pkt = BFDPacket . bfd_parse ( data ) <EOL> if not isinstance ( bfd_pkt , bfd . bfd ) : <EOL> return <EOL> if bfd_pkt . ver != <NUM_LIT:1> : <EOL> return <EOL> if bfd_pkt . flags & bfd . BFD_FLAG_AUTH_PRESENT : <EOL> if bfd_pkt . length < <NUM_LIT> : <EOL> return <EOL> else : <EOL> if bfd_pkt . length < <NUM_LIT> : <EOL> return <EOL> if bfd_pkt . detect_mult == <NUM_LIT:0> : <EOL> return <EOL> if bfd_pkt . flags & bfd . BFD_FLAG_MULTIPOINT : <EOL> return <EOL> if bfd_pkt . my_discr == <NUM_LIT:0> : <EOL> return <EOL> if bfd_pkt . your_discr != <NUM_LIT:0> and bfd_pkt . your_discr not in self . session : <EOL> return <EOL> if bfd_pkt . your_discr == <NUM_LIT:0> and bfd_pkt . state not in [ bfd . BFD_STATE_ADMIN_DOWN , <EOL> bfd . BFD_STATE_DOWN ] : <EOL> return <EOL> sess_my_discr = None <EOL> if bfd_pkt . your_discr == <NUM_LIT:0> : <EOL> for s in self . session . values ( ) : <EOL> if s . dpid == datapath . id and s . ofport == in_port : <EOL> sess_my_discr = s . my_discr <EOL> break <EOL> if sess_my_discr is None : <EOL> return <EOL> else : <EOL> sess_my_discr = bfd_pkt . your_discr <EOL> sess = self . session [ sess_my_discr ] <EOL> if bfd_pkt . flags & bfd . BFD_FLAG_AUTH_PRESENT and sess . _auth_type == <NUM_LIT:0> : <EOL> return <EOL> if bfd_pkt . flags & bfd . BFD_FLAG_AUTH_PRESENT == <NUM_LIT:0> and sess . _auth_type != <NUM_LIT:0> : <EOL> return <EOL> if bfd_pkt . flags & bfd . BFD_FLAG_AUTH_PRESENT : <EOL> if sess . _auth_type == <NUM_LIT:0> : <EOL> return <EOL> if bfd_pkt . auth_cls . auth_type != sess . _auth_type : <EOL> return <EOL> if sess . _auth_type in [ bfd . BFD_AUTH_KEYED_MD5 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_MD5 , <EOL> bfd . BFD_AUTH_KEYED_SHA1 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_SHA1 ] : <EOL> if sess . _auth_seq_known : <EOL> if bfd_pkt . auth_cls . seq < sess . _rcv_auth_seq : <EOL> return <EOL> if sess . _auth_type in [ bfd . BFD_AUTH_METICULOUS_KEYED_MD5 , <EOL> bfd . BFD_AUTH_METICULOUS_KEYED_SHA1 ] : <EOL> if bfd_pkt . auth_cls . seq <= sess . _rcv_auth_seq : <EOL> return <EOL> if bfd_pkt . auth_cls . seq > sess . _rcv_auth_seq + <NUM_LIT:3> * sess . _detect_mult : <EOL> return <EOL> if not bfd_pkt . authenticate ( sess . _auth_keys ) : <EOL> LOG . debug ( "<STR_LIT>" , <EOL> hex ( sess . _local_discr ) ) <EOL> return <EOL> if sess is not None : <EOL> if not sess . _remote_addr_config : <EOL> sess . set_remote_addr ( eth . src , ip_pkt . src ) <EOL> sess . recv ( bfd_pkt ) </s>
