Response to dhcp packets with lport MAC
(instead of broadcast) Change-Id: I0e56fc0658c6135111b588d78d63b57fc2dc6b0e Closes-Bug:1703168
This commit is contained in:
parent
ed24870dae
commit
62f243e4da
|
@ -65,8 +65,22 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
self.packet_in_handler)
|
||||
self._dhcp_ip_by_subnet = {}
|
||||
|
||||
def _get_dhcp_port_by_network(self, network_unique_key):
|
||||
|
||||
lswitch = self.db_store.get_one(l2.LogicalSwitch(
|
||||
unique_key=network_unique_key),
|
||||
index=l2.LogicalSwitch.get_index('unique_key'))
|
||||
|
||||
return self.db_store.get_one(
|
||||
l2.LogicalPort(
|
||||
device_owner=n_const.DEVICE_OWNER_DHCP,
|
||||
lswitch=lswitch
|
||||
),
|
||||
index=l2.LogicalPort.get_index('switch,owner')
|
||||
)
|
||||
|
||||
def switch_features_handler(self, ev):
|
||||
self._install_dhcp_broadcast_match_flow()
|
||||
self._install_dhcp_packet_match_flow()
|
||||
self.add_flow_go_to_table(const.DHCP_TABLE,
|
||||
const.PRIORITY_DEFAULT,
|
||||
const.L2_LOOKUP_TABLE)
|
||||
|
@ -94,6 +108,12 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
index=l2.LogicalPort.get_index('unique_key'),
|
||||
)
|
||||
|
||||
network_key = msg.match.get('metadata')
|
||||
dhcp_lport = self._get_dhcp_port_by_network(network_key)
|
||||
if not dhcp_lport:
|
||||
LOG.error("No DHCP port for network {}".format(str(network_key)))
|
||||
return
|
||||
|
||||
if self._check_port_limit(lport):
|
||||
self._block_port_dhcp_traffic(unique_key, lport)
|
||||
LOG.warning("pass rate limit for %(port_id)s blocking DHCP "
|
||||
|
@ -106,11 +126,11 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
LOG.error("Port %s no longer found.", lport.id)
|
||||
return
|
||||
try:
|
||||
self._handle_dhcp_request(pkt, lport)
|
||||
self._handle_dhcp_request(pkt, lport, dhcp_lport)
|
||||
except Exception:
|
||||
LOG.exception("Unable to handle packet %s", msg)
|
||||
|
||||
def _handle_dhcp_request(self, packet, lport):
|
||||
def _handle_dhcp_request(self, packet, lport, dhcp_port):
|
||||
dhcp_packet = packet.get_protocol(dhcp.dhcp)
|
||||
dhcp_message_type = self._get_dhcp_message_type_opt(dhcp_packet)
|
||||
send_packet = None
|
||||
|
@ -119,7 +139,8 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
packet,
|
||||
dhcp_packet,
|
||||
dhcp.DHCP_OFFER,
|
||||
lport)
|
||||
lport,
|
||||
dhcp_port)
|
||||
LOG.info("sending DHCP offer for port IP %(port_ip)s "
|
||||
"port id %(port_id)s",
|
||||
{'port_ip': lport.ip, 'port_id': lport.id})
|
||||
|
@ -128,7 +149,8 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
packet,
|
||||
dhcp_packet,
|
||||
dhcp.DHCP_ACK,
|
||||
lport)
|
||||
lport,
|
||||
dhcp_port)
|
||||
LOG.info("sending DHCP ACK for port IP %(port_ip)s "
|
||||
"port id %(tunnel_id)s",
|
||||
{'port_ip': lport.ip,
|
||||
|
@ -141,7 +163,7 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
self.dispatch_packet(send_packet, unique_key)
|
||||
|
||||
def _create_dhcp_response(self, packet, dhcp_request,
|
||||
response_type, lport):
|
||||
response_type, lport, dhcp_port):
|
||||
pkt_ipv4 = packet.get_protocol(ipv4.ipv4)
|
||||
pkt_ethernet = packet.get_protocol(ethernet.ethernet)
|
||||
|
||||
|
@ -169,7 +191,7 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
dhcp_response.add_protocol(ethernet.ethernet(
|
||||
ethertype=ether.ETH_TYPE_IP,
|
||||
dst=pkt_ethernet.src,
|
||||
src=pkt_ethernet.dst))
|
||||
src=dhcp_port.mac))
|
||||
dhcp_response.add_protocol(ipv4.ipv4(dst=pkt_ipv4.src,
|
||||
src=dhcp_server_address,
|
||||
proto=pkt_ipv4.proto))
|
||||
|
@ -375,11 +397,10 @@ class DHCPApp(df_base_app.DFlowApp):
|
|||
table_id=const.DHCP_TABLE,
|
||||
match=match)
|
||||
|
||||
def _install_dhcp_broadcast_match_flow(self):
|
||||
def _install_dhcp_packet_match_flow(self):
|
||||
parser = self.parser
|
||||
|
||||
match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
|
||||
eth_dst=const.BROADCAST_MAC,
|
||||
ip_proto=n_const.PROTO_NUM_UDP,
|
||||
udp_src=const.DHCP_CLIENT_PORT,
|
||||
udp_dst=const.DHCP_SERVER_PORT)
|
||||
|
|
|
@ -179,7 +179,6 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
# DHCP packets with the vm mac pass
|
||||
match = parser.OFPMatch(reg6=unique_key,
|
||||
eth_src=vm_mac,
|
||||
eth_dst=const.BROADCAST_MAC,
|
||||
eth_type=ether.ETH_TYPE_IP,
|
||||
ip_proto=n_const.PROTO_NUM_UDP,
|
||||
udp_src=const.DHCP_CLIENT_PORT,
|
||||
|
@ -225,7 +224,6 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
# Remove DHCP packets with the vm mac pass
|
||||
match = parser.OFPMatch(reg6=unique_key,
|
||||
eth_src=vm_mac,
|
||||
eth_dst=const.BROADCAST_MAC,
|
||||
eth_type=ether.ETH_TYPE_IP,
|
||||
ip_proto=n_const.PROTO_NUM_UDP,
|
||||
udp_src=const.DHCP_CLIENT_PORT,
|
||||
|
|
|
@ -138,6 +138,7 @@ EVENT_UNBIND_REMOTE = 'unbind_remote'
|
|||
'chassis_id': 'binding.chassis.id',
|
||||
'lswitch_id': 'lswitch.id',
|
||||
'ip,lswitch': ('ips', 'lswitch.id'),
|
||||
'switch,owner': ('lswitch.unique_key', 'device_owner')
|
||||
})
|
||||
class LogicalPort(mf.ModelBase, mixins.Name, mixins.Version, mixins.Topic,
|
||||
mixins.UniqueKey, mixins.BasicEvents):
|
||||
|
|
|
@ -33,7 +33,7 @@ class TestOVSFlowsForDHCP(test_base.DFTestBase):
|
|||
return ip['ip_address']
|
||||
return None
|
||||
|
||||
def test_broadcast_dhcp_rule(self):
|
||||
def test_dhcp_packet_rule(self):
|
||||
found_dhcp_cast_flow = False
|
||||
ovs = utils.OvsFlowsParser()
|
||||
flows = ovs.dump(self.integration_bridge)
|
||||
|
@ -43,7 +43,7 @@ class TestOVSFlowsForDHCP(test_base.DFTestBase):
|
|||
for flow in flows:
|
||||
if (flow['table'] == str(constants.SERVICES_CLASSIFICATION_TABLE)
|
||||
and flow['actions'] == goto_dhcp):
|
||||
if ('udp,dl_dst=' + constants.BROADCAST_MAC + dhcp_ports
|
||||
if ('udp' + dhcp_ports
|
||||
in flow['match']):
|
||||
found_dhcp_cast_flow = True
|
||||
break
|
||||
|
|
|
@ -71,10 +71,9 @@ class TestOVSFlowsForPortSecurity(test_base.DFTestBase):
|
|||
# priority: High, match: reg6=unique_key, dl_src=$vm_mac,
|
||||
# dl_dst=ff:ff:ff:ff:ff:ff, udp, tp_src=68, tp_dst=67,
|
||||
# actions: goto const.EGRESS_CONNTRACK_TABLE
|
||||
dl_dst_match = "dl_dst=" + const.BROADCAST_MAC
|
||||
expected_flow_list.append({
|
||||
"priority": str(const.PRIORITY_HIGH),
|
||||
"match_list": [unique_key_match, dl_src_match, dl_dst_match,
|
||||
"match_list": [unique_key_match, dl_src_match,
|
||||
"udp", "tp_src=" + str(const.DHCP_CLIENT_PORT),
|
||||
"tp_dst=" + str(const.DHCP_SERVER_PORT)],
|
||||
"actions": goto_conntrack_table_action
|
||||
|
|
|
@ -96,14 +96,14 @@ class TestDHCPApp(test_app_base.DFAppTestBase):
|
|||
lswitch=test_app_base.fake_logic_switch1,
|
||||
subnets=test_app_base.fake_lswitch_default_subnets,
|
||||
ips=('10.0.0.2',),
|
||||
macs=("11:22:33:44:55:66",),
|
||||
device_owner=n_const.DEVICE_OWNER_DHCP
|
||||
)
|
||||
|
||||
return fake_dhcp_port
|
||||
|
||||
def _build_dhcp_test_fake_lport(self, dhcp_params=None):
|
||||
def _build_dhcp_test_fake_lport(self, dhcp_port, dhcp_params=None):
|
||||
|
||||
dhcp_port = self._create_dhcp_port()
|
||||
self.app._lport_created(dhcp_port)
|
||||
|
||||
fake_loprt = test_app_base.make_fake_local_port(
|
||||
|
@ -115,7 +115,7 @@ class TestDHCPApp(test_app_base.DFAppTestBase):
|
|||
|
||||
return fake_loprt
|
||||
|
||||
def _send_dhcp_req_to_app(self, lport, options=None):
|
||||
def _send_dhcp_req_to_app(self, lport, dhcp_port, options=None):
|
||||
req = dhcp.dhcp(op=dhcp.DHCP_DISCOVER,
|
||||
chaddr='aa:aa:aa:aa:aa:aa',
|
||||
options=dhcp.options(options))
|
||||
|
@ -123,7 +123,8 @@ class TestDHCPApp(test_app_base.DFAppTestBase):
|
|||
dhcp_response_pkt = self.app._create_dhcp_response(pkt,
|
||||
req,
|
||||
dhcp.DHCP_OFFER,
|
||||
lport)
|
||||
lport,
|
||||
dhcp_port)
|
||||
|
||||
return dhcp_response_pkt
|
||||
|
||||
|
@ -135,18 +136,20 @@ class TestDHCPApp(test_app_base.DFAppTestBase):
|
|||
return pkt
|
||||
|
||||
def test_dhcp_repsonse(self):
|
||||
|
||||
fake_loprt = self._build_dhcp_test_fake_lport()
|
||||
dhcp_response_pkt = self._send_dhcp_req_to_app(fake_loprt)
|
||||
dhcp_port = self._create_dhcp_port()
|
||||
fake_loprt = self._build_dhcp_test_fake_lport(dhcp_port)
|
||||
dhcp_response_pkt = self._send_dhcp_req_to_app(fake_loprt, dhcp_port)
|
||||
self.assertTrue(dhcp_response_pkt)
|
||||
dhcp_response = dhcp_response_pkt.get_protocol(dhcp.dhcp)
|
||||
self.assertEqual('10.0.0.1', str(dhcp_response.yiaddr))
|
||||
dhcp_eth = dhcp_response_pkt.get_protocol(ethernet.ethernet)
|
||||
self.assertEqual("11:22:33:44:55:66", str(dhcp_eth.src))
|
||||
|
||||
def _create_dhcp_reponse(self, dhcp_opts, requested):
|
||||
|
||||
dhcp_port = self._create_dhcp_port()
|
||||
dhcp_params = {"opts": {} if not dhcp_opts else dhcp_opts}
|
||||
|
||||
fake_lport = self._build_dhcp_test_fake_lport(dhcp_params)
|
||||
fake_lport = self._build_dhcp_test_fake_lport(dhcp_port, dhcp_params)
|
||||
requested_option_connected = ''.join([chr(x) for x in requested])
|
||||
|
||||
option_list = [dhcp.option(dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT,
|
||||
|
@ -155,6 +158,7 @@ class TestDHCPApp(test_app_base.DFAppTestBase):
|
|||
]
|
||||
|
||||
dhcp_response_pkt = self._send_dhcp_req_to_app(fake_lport,
|
||||
dhcp_port,
|
||||
option_list)
|
||||
|
||||
dhcp_res = dhcp_response_pkt.get_protocol(dhcp.dhcp)
|
||||
|
|
Loading…
Reference in New Issue