patching service unicast messaging for loopback interface
IPv6 does not support multicast messaging on the loopback interface. Therefore to support patch agent to controller messaging when the management network is associated with the loopback interface it must operate using unicast messaging. This is sufficient since it does not need to communicate with multiple process instances when operating in this local mode. Change-Id: I95efd06be9717a76ccbd543c1fd16408fd89dbeb Closes-Bug: #1830779 Signed-off-by: Matt Peters <matt.peters@windriver.com>
This commit is contained in:
parent
4b1e9e453f
commit
319252db74
|
@ -64,18 +64,19 @@ class PatchService:
|
||||||
self.sock_out.bind((mgmt_ip, 0))
|
self.sock_out.bind((mgmt_ip, 0))
|
||||||
self.sock_in.bind(('', self.port))
|
self.sock_in.bind(('', self.port))
|
||||||
|
|
||||||
# These options are for outgoing multicast messages
|
if self.mcast_addr:
|
||||||
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, interface_addr)
|
# These options are for outgoing multicast messages
|
||||||
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
|
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, interface_addr)
|
||||||
# Since only the controllers are sending to this address,
|
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
|
||||||
# we want the loopback so the local agent can receive it
|
# Since only the controllers are sending to this address,
|
||||||
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
|
# we want the loopback so the local agent can receive it
|
||||||
|
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
|
||||||
|
|
||||||
# Register the multicast group
|
# Register the multicast group
|
||||||
group = socket.inet_pton(socket.AF_INET, self.mcast_addr)
|
group = socket.inet_pton(socket.AF_INET, self.mcast_addr)
|
||||||
mreq = struct.pack('=4s4s', group, interface_addr)
|
mreq = struct.pack('=4s4s', group, interface_addr)
|
||||||
|
|
||||||
self.sock_in.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
|
self.sock_in.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
|
||||||
|
|
||||||
return self.sock_in
|
return self.sock_in
|
||||||
|
|
||||||
|
@ -106,18 +107,19 @@ class PatchService:
|
||||||
self.sock_out.bind((mgmt_ip, 0))
|
self.sock_out.bind((mgmt_ip, 0))
|
||||||
self.sock_in.bind(('', self.port))
|
self.sock_in.bind(('', self.port))
|
||||||
|
|
||||||
# These options are for outgoing multicast messages
|
if self.mcast_addr:
|
||||||
mgmt_ifindex = utils.if_nametoindex(cfg.get_mgmt_iface())
|
# These options are for outgoing multicast messages
|
||||||
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, mgmt_ifindex)
|
mgmt_ifindex = utils.if_nametoindex(cfg.get_mgmt_iface())
|
||||||
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 1)
|
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, mgmt_ifindex)
|
||||||
# Since only the controllers are sending to this address,
|
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 1)
|
||||||
# we want the loopback so the local agent can receive it
|
# Since only the controllers are sending to this address,
|
||||||
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)
|
# we want the loopback so the local agent can receive it
|
||||||
|
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)
|
||||||
|
|
||||||
# Register the multicast group
|
# Register the multicast group
|
||||||
if_index_packed = struct.pack('I', mgmt_ifindex)
|
if_index_packed = struct.pack('I', mgmt_ifindex)
|
||||||
group = socket.inet_pton(socket.AF_INET6, self.mcast_addr) + if_index_packed
|
group = socket.inet_pton(socket.AF_INET6, self.mcast_addr) + if_index_packed
|
||||||
self.sock_in.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)
|
self.sock_in.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)
|
||||||
|
|
||||||
return self.sock_in
|
return self.sock_in
|
||||||
|
|
||||||
|
@ -145,6 +147,10 @@ class PatchService:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def audit_socket(self):
|
def audit_socket(self):
|
||||||
|
if not self.mcast_addr:
|
||||||
|
# Multicast address not configured, therefore nothing to do
|
||||||
|
return
|
||||||
|
|
||||||
# Ensure multicast address is still allocated
|
# Ensure multicast address is still allocated
|
||||||
cmd = "ip maddr show %s | awk 'BEGIN {ORS=\"\"}; {if ($2 == \"%s\") print $2}'" % \
|
cmd = "ip maddr show %s | awk 'BEGIN {ORS=\"\"}; {if ($2 == \"%s\") print $2}'" % \
|
||||||
(cfg.get_mgmt_iface(), self.mcast_addr)
|
(cfg.get_mgmt_iface(), self.mcast_addr)
|
||||||
|
|
|
@ -114,7 +114,6 @@ def get_mgmt_iface():
|
||||||
try:
|
try:
|
||||||
value = str(config.get('platform_conf', 'management_interface'))
|
value = str(config.get('platform_conf', 'management_interface'))
|
||||||
|
|
||||||
global nodetype
|
|
||||||
mgmt_if = value
|
mgmt_if = value
|
||||||
|
|
||||||
platform_conf_mtime = os.stat(tsc.PLATFORM_CONF_FILE).st_mtime
|
platform_conf_mtime = os.stat(tsc.PLATFORM_CONF_FILE).st_mtime
|
||||||
|
|
|
@ -43,3 +43,5 @@ CLI_OPT_RECURSIVE = '--recursive'
|
||||||
CLI_OPT_RELEASE = '--release'
|
CLI_OPT_RELEASE = '--release'
|
||||||
|
|
||||||
ENABLE_DEV_CERTIFICATE_PATCH_IDENTIFIER = 'ENABLE_DEV_CERTIFICATE'
|
ENABLE_DEV_CERTIFICATE_PATCH_IDENTIFIER = 'ENABLE_DEV_CERTIFICATE'
|
||||||
|
|
||||||
|
LOOPBACK_INTERFACE_NAME = "lo"
|
||||||
|
|
|
@ -172,9 +172,10 @@ class PatchMessageHelloAgentAck(messages.PatchMessage):
|
||||||
LOG.error("Should not get here")
|
LOG.error("Should not get here")
|
||||||
|
|
||||||
def send(self, sock):
|
def send(self, sock):
|
||||||
|
global pa
|
||||||
self.encode()
|
self.encode()
|
||||||
message = json.dumps(self.message)
|
message = json.dumps(self.message)
|
||||||
sock.sendto(message, (cfg.controller_mcast_group, cfg.controller_port))
|
sock.sendto(message, (pa.controller_address, cfg.controller_port))
|
||||||
|
|
||||||
|
|
||||||
class PatchMessageQueryDetailed(messages.PatchMessage):
|
class PatchMessageQueryDetailed(messages.PatchMessage):
|
||||||
|
@ -292,6 +293,7 @@ class PatchAgent(PatchService):
|
||||||
PatchService.__init__(self)
|
PatchService.__init__(self)
|
||||||
self.sock_out = None
|
self.sock_out = None
|
||||||
self.sock_in = None
|
self.sock_in = None
|
||||||
|
self.controller_address = None
|
||||||
self.listener = None
|
self.listener = None
|
||||||
self.changes = False
|
self.changes = False
|
||||||
self.installed = {}
|
self.installed = {}
|
||||||
|
@ -323,8 +325,15 @@ class PatchAgent(PatchService):
|
||||||
if self.port != cfg.agent_port:
|
if self.port != cfg.agent_port:
|
||||||
self.port = cfg.agent_port
|
self.port = cfg.agent_port
|
||||||
|
|
||||||
if self.mcast_addr != cfg.agent_mcast_group:
|
# Loopback interface does not support multicast messaging, therefore
|
||||||
|
# revert to using unicast messaging when configured against the
|
||||||
|
# loopback device
|
||||||
|
if cfg.get_mgmt_iface() == constants.LOOPBACK_INTERFACE_NAME:
|
||||||
|
self.mcast_addr = None
|
||||||
|
self.controller_address = cfg.get_mgmt_ip()
|
||||||
|
else:
|
||||||
self.mcast_addr = cfg.agent_mcast_group
|
self.mcast_addr = cfg.agent_mcast_group
|
||||||
|
self.controller_address = cfg.controller_mcast_group
|
||||||
|
|
||||||
def setup_tcp_socket(self):
|
def setup_tcp_socket(self):
|
||||||
address_family = utils.get_management_family()
|
address_family = utils.get_management_family()
|
||||||
|
|
|
@ -230,9 +230,10 @@ class PatchMessageHello(messages.PatchMessage):
|
||||||
resp.send(sock)
|
resp.send(sock)
|
||||||
|
|
||||||
def send(self, sock):
|
def send(self, sock):
|
||||||
|
global pc
|
||||||
self.encode()
|
self.encode()
|
||||||
message = json.dumps(self.message)
|
message = json.dumps(self.message)
|
||||||
sock.sendto(message, (cfg.controller_mcast_group, cfg.controller_port))
|
sock.sendto(message, (pc.controller_address, cfg.controller_port))
|
||||||
|
|
||||||
|
|
||||||
class PatchMessageHelloAck(messages.PatchMessage):
|
class PatchMessageHelloAck(messages.PatchMessage):
|
||||||
|
@ -254,9 +255,10 @@ class PatchMessageHelloAck(messages.PatchMessage):
|
||||||
pc.controller_neighbours_lock.release()
|
pc.controller_neighbours_lock.release()
|
||||||
|
|
||||||
def send(self, sock):
|
def send(self, sock):
|
||||||
|
global pc
|
||||||
self.encode()
|
self.encode()
|
||||||
message = json.dumps(self.message)
|
message = json.dumps(self.message)
|
||||||
sock.sendto(message, (cfg.controller_mcast_group, cfg.controller_port))
|
sock.sendto(message, (pc.controller_address, cfg.controller_port))
|
||||||
|
|
||||||
|
|
||||||
class PatchMessageSyncReq(messages.PatchMessage):
|
class PatchMessageSyncReq(messages.PatchMessage):
|
||||||
|
@ -283,10 +285,11 @@ class PatchMessageSyncReq(messages.PatchMessage):
|
||||||
resp.send(sock)
|
resp.send(sock)
|
||||||
|
|
||||||
def send(self, sock):
|
def send(self, sock):
|
||||||
|
global pc
|
||||||
LOG.info("sending sync req")
|
LOG.info("sending sync req")
|
||||||
self.encode()
|
self.encode()
|
||||||
message = json.dumps(self.message)
|
message = json.dumps(self.message)
|
||||||
sock.sendto(message, (cfg.controller_mcast_group, cfg.controller_port))
|
sock.sendto(message, (pc.controller_address, cfg.controller_port))
|
||||||
|
|
||||||
|
|
||||||
class PatchMessageSyncComplete(messages.PatchMessage):
|
class PatchMessageSyncComplete(messages.PatchMessage):
|
||||||
|
@ -309,10 +312,11 @@ class PatchMessageSyncComplete(messages.PatchMessage):
|
||||||
pc.controller_neighbours_lock.release()
|
pc.controller_neighbours_lock.release()
|
||||||
|
|
||||||
def send(self, sock):
|
def send(self, sock):
|
||||||
|
global pc
|
||||||
LOG.info("sending sync complete")
|
LOG.info("sending sync complete")
|
||||||
self.encode()
|
self.encode()
|
||||||
message = json.dumps(self.message)
|
message = json.dumps(self.message)
|
||||||
sock.sendto(message, (cfg.controller_mcast_group, cfg.controller_port))
|
sock.sendto(message, (pc.controller_address, cfg.controller_port))
|
||||||
|
|
||||||
|
|
||||||
class PatchMessageHelloAgent(messages.PatchMessage):
|
class PatchMessageHelloAgent(messages.PatchMessage):
|
||||||
|
@ -328,10 +332,11 @@ class PatchMessageHelloAgent(messages.PatchMessage):
|
||||||
LOG.error("Should not get here")
|
LOG.error("Should not get here")
|
||||||
|
|
||||||
def send(self, sock):
|
def send(self, sock):
|
||||||
|
global pc
|
||||||
self.encode()
|
self.encode()
|
||||||
message = json.dumps(self.message)
|
message = json.dumps(self.message)
|
||||||
local_hostname = utils.ip_to_versioned_localhost(cfg.agent_mcast_group)
|
local_hostname = utils.ip_to_versioned_localhost(cfg.agent_mcast_group)
|
||||||
sock.sendto(message, (cfg.agent_mcast_group, cfg.agent_port))
|
sock.sendto(message, (pc.agent_address, cfg.agent_port))
|
||||||
sock.sendto(message, (local_hostname, cfg.agent_port))
|
sock.sendto(message, (local_hostname, cfg.agent_port))
|
||||||
|
|
||||||
|
|
||||||
|
@ -549,9 +554,10 @@ class PatchMessageDropHostReq(messages.PatchMessage):
|
||||||
return
|
return
|
||||||
|
|
||||||
def send(self, sock):
|
def send(self, sock):
|
||||||
|
global pc
|
||||||
self.encode()
|
self.encode()
|
||||||
message = json.dumps(self.message)
|
message = json.dumps(self.message)
|
||||||
sock.sendto(message, (cfg.controller_mcast_group, cfg.controller_port))
|
sock.sendto(message, (pc.controller_address, cfg.controller_port))
|
||||||
|
|
||||||
|
|
||||||
class PatchController(PatchService):
|
class PatchController(PatchService):
|
||||||
|
@ -577,6 +583,8 @@ class PatchController(PatchService):
|
||||||
|
|
||||||
self.sock_out = None
|
self.sock_out = None
|
||||||
self.sock_in = None
|
self.sock_in = None
|
||||||
|
self.controller_address = None
|
||||||
|
self.agent_address = None
|
||||||
self.patch_op_counter = 1
|
self.patch_op_counter = 1
|
||||||
self.patch_data = PatchData()
|
self.patch_data = PatchData()
|
||||||
self.patch_data.load_all()
|
self.patch_data.load_all()
|
||||||
|
@ -605,8 +613,18 @@ class PatchController(PatchService):
|
||||||
if self.port != cfg.controller_port:
|
if self.port != cfg.controller_port:
|
||||||
self.port = cfg.controller_port
|
self.port = cfg.controller_port
|
||||||
|
|
||||||
if self.mcast_addr != cfg.controller_mcast_group:
|
# Loopback interface does not support multicast messaging, therefore
|
||||||
|
# revert to using unicast messaging when configured against the
|
||||||
|
# loopback device
|
||||||
|
if cfg.get_mgmt_iface() == constants.LOOPBACK_INTERFACE_NAME:
|
||||||
|
mgmt_ip = cfg.get_mgmt_ip()
|
||||||
|
self.mcast_addr = None
|
||||||
|
self.controller_address = mgmt_ip
|
||||||
|
self.agent_address = mgmt_ip
|
||||||
|
else:
|
||||||
self.mcast_addr = cfg.controller_mcast_group
|
self.mcast_addr = cfg.controller_mcast_group
|
||||||
|
self.controller_address = cfg.controller_mcast_group
|
||||||
|
self.agent_address = cfg.agent_mcast_group
|
||||||
|
|
||||||
def socket_lock_acquire(self):
|
def socket_lock_acquire(self):
|
||||||
self.socket_lock.acquire()
|
self.socket_lock.acquire()
|
||||||
|
|
Loading…
Reference in New Issue