On Mon, Mar 27, 2017 at 9:45 PM, Guru Shetty <g...@ovn.org> wrote: > > > On 27 March 2017 at 07:13, <nusid...@redhat.com> wrote: > >> From: Numan Siddique <nusid...@redhat.com> >> >> OVN implements native DNS resolution which can be used to resolve the >> internal DNS names belonging to a logical datapath. >> >> To support this, a new table 'DNS' is added in the NB DB. A new column >> 'dns_lookups' is added in 'Logical_Switch' table which references to the >> 'DNS' table. >> >> Following flows are added for each logical switch which has atleast one >> DNS entry in the 'dns_lookups' column >> - A logical flow in DNS_LOOKUP stage which uses the action 'dns_lookup' >> to transform the DNS query to DNS reply packet and advances >> to the next stage - DNS_RESPONSE. >> >> - A logical flow in DNS_RESPONSE stage which implements the DNS responder >> by sending the DNS reply from previous stage back to the inport. >> >> Signed-off-by: Numan Siddique <nusid...@redhat.com> >> --- >> ovn/northd/ovn-northd.8.xml | 88 ++++++++++- >> ovn/northd/ovn-northd.c | 150 ++++++++++++++++++- >> ovn/ovn-nb.ovsschema | 16 +- >> ovn/ovn-nb.xml | 20 ++- >> ovn/utilities/ovn-nbctl.c | 3 + >> tests/ovn.at | 353 ++++++++++++++++++++++++++++++ >> ++++++++++++++ >> 6 files changed, 618 insertions(+), 12 deletions(-) >> >> diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml >> index ab8fd88..a3fe2a8 100644 >> --- a/ovn/northd/ovn-northd.8.xml >> +++ b/ovn/northd/ovn-northd.8.xml >> @@ -724,7 +724,73 @@ output; >> </li> >> </ul> >> >> - <h3>Ingress Table 13 Destination Lookup</h3> >> + <h3>Ingress Table 13 DNS Lookup</h3> >> + >> + <p> >> + This table looks up and resolves the DNS names of the logical ports >> + if configured with the host names. >> + </p> >> + >> + <ul> >> + <li> >> + <p> >> + A priority-100 logical flow for each logical switch data path >> + if at least one of its logical port is configured with >> + <code>hostname</code> which matches the IPv4 and IPv6 packets >> with >> + <code>udp.src</code> = 53 and applies the action >> + <code>dns_lkup</code> and advances the packet to the next >> table. >> + </p> >> + >> + <pre> >> +reg0[4] = dns_lkup(); next; >> + </pre> >> + >> + <p> >> + For valid DNS packets, this transforms the packet into a DNS >> + reply if the DNS name can be resolved, and stores 1 into >> reg0[4]. >> + For failed DNS resolution or other kinds of packets, it just >> stores >> + 0 into reg0[4]. Either way, it continues to the next table. >> + </p> >> + </li> >> + </ul> >> + >> + <h3>Ingress Table 14 DNS Responses</h3> >> + >> + <p> >> + This table implements DNS responder for the DNS replies generated >> by >> + the previous table. >> + </p> >> + >> + <ul> >> + <li> >> + <p> >> + A priority-100 logical flow for each logical switch data path >> + if at least one of its logical port is configured with >> + <code>hostname</code> which matches IPv4 and IPv6 packets with >> + <code>udp.src == 53 && reg0[4] == 1</code> and responds >> + back to the <code>inport</code> after applying these >> + actions. If <code>reg0[4]</code> is set to 1, it means that >> the >> + action <code>dns_lkup</code> was successful. >> + </p> >> + >> + <pre> >> +eth.dst <-> eth.src; >> +ip4.src <-> ip4.dst; >> +udp.dst = udp.src; >> +udp.src = 53; >> +outport = <var>P</var>; >> +flags.loopback = 1; >> +output; >> + </pre> >> + >> + <p> >> + (This terminates ingress packet processing; the packet does >> not go >> + to the next ingress table.) >> + </p> >> + </li> >> + </ul> >> + >> + <h3>Ingress Table 15 Destination Lookup</h3> >> >> <p> >> This table implements switching behavior. It contains these >> logical >> @@ -834,11 +900,23 @@ output; >> </p> >> >> <p> >> - Also a priority 34000 logical flow is added for each logical port >> which >> - has DHCPv4 options defined to allow the DHCPv4 reply packet and >> which has >> - DHCPv6 options defined to allow the DHCPv6 reply packet from the >> - <code>Ingress Table 12: DHCP responses</code>. >> + Also the following flows are added. >> </p> >> + <ul> >> + <li> >> + A Priority 34000 logical flow is added for each logical port >> which >> + has DHCPv4 options defined to allow the DHCPv4 reply packet and >> which has >> + DHCPv6 options defined to allow the DHCPv6 reply packet from the >> + <code>Ingress Table 12: DHCP responses</code>. >> + </li> >> + >> + <li> >> + A Priority 34000 logical flow for each logical switch data path >> if at >> + least one of its logical port is configured with hostname >> + which allows the DNS reply packet from the >> + <code>Ingress Table 14:DNS responses</code>. >> + </li> >> + </ul> >> >> <h3>Egress Table 7: Egress Port Security - IP</h3> >> >> diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c >> index 8c8f16b..d125651 100644 >> --- a/ovn/northd/ovn-northd.c >> +++ b/ovn/northd/ovn-northd.c >> @@ -112,7 +112,9 @@ enum ovn_stage { >> PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 10, "ls_in_arp_rsp") >> \ >> PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 11, >> "ls_in_dhcp_options") \ >> PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 12, >> "ls_in_dhcp_response") \ >> - PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 13, "ls_in_l2_lkup") >> \ >> + PIPELINE_STAGE(SWITCH, IN, DNS_LOOKUP, 13, "ls_in_dns_lookup") >> \ >> + PIPELINE_STAGE(SWITCH, IN, DNS_RESPONSE, 14, "ls_in_dns_response") >> \ >> + PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 15, "ls_in_l2_lkup") >> \ >> \ >> /* Logical switch egress stages. */ \ >> PIPELINE_STAGE(SWITCH, OUT, PRE_LB, 0, "ls_out_pre_lb") \ >> @@ -160,6 +162,7 @@ enum ovn_stage { >> #define REGBIT_CONNTRACK_COMMIT "reg0[1]" >> #define REGBIT_CONNTRACK_NAT "reg0[2]" >> #define REGBIT_DHCP_OPTS_RESULT "reg0[3]" >> +#define REGBIT_DNS_LOOKUP_RESULT "reg0[4]" >> >> /* Register definitions for switches and routers. */ >> #define REGBIT_NAT_REDIRECT "reg9[0]" >> @@ -2815,7 +2818,13 @@ build_acls(struct ovn_datapath *od, struct hmap >> *lflows) >> } >> >> /* Add 34000 priority flow to allow DHCP reply from ovn-controller >> to all >> - * logical ports of the datapath if the CMS has configured DHCPv4 >> options*/ >> + * logical ports of the datapath if the CMS has configured DHCPv4 >> options. >> + * >> + * Add one 34000 priority flow to allow DNS reply from >> ovn-controller to all >> + * logical ports of the datapath if the CMS has configured DNS >> parameters >> + * for atleast one logical port. >> + * */ >> + bool dns_flow_added = false; >> for (size_t i = 0; i < od->nbs->n_ports; i++) { >> if (od->nbs->ports[i]->dhcpv4_options) { >> const char *server_id = smap_get( >> @@ -2865,6 +2874,16 @@ build_acls(struct ovn_datapath *od, struct hmap >> *lflows) >> ds_destroy(&match); >> } >> } >> + >> + if (!dns_flow_added && smap_get(&od->nbs->ports[i]->options, >> + "hostname")) { >> + const char *actions = has_stateful ? "ct_commit; next;" : >> + "next;"; >> + ovn_lflow_add( >> + lflows, od, S_SWITCH_OUT_ACL, 34000, "udp && udp.src == >> 53", >> + actions); >> + dns_flow_added = true; >> + } >> } >> } >> >> @@ -3303,8 +3322,43 @@ build_lswitch_flows(struct hmap *datapaths, struct >> hmap *ports, >> } >> } >> >> + /* Logical switch ingress table 13 and 14: DNS lookup and response >> + * priority 100 flows.*/ >> + HMAP_FOR_EACH (od, key_node, datapaths) { >> + if (!od->nbs || !od->nbs->n_dns_lookups) { >> + continue; >> + } >> + >> + struct ds match; >> + struct ds action; >> + ds_init(&match); >> + ds_init(&action); >> + ds_put_cstr(&match, "ip && udp.dst == 53"); >> + ds_put_format(&action, >> + REGBIT_DNS_LOOKUP_RESULT" = dns_lookup(); next;"); >> + ovn_lflow_add(lflows, od, S_SWITCH_IN_DNS_LOOKUP, 100, >> + ds_cstr(&match), ds_cstr(&action)); >> + ds_clear(&action); >> + ds_put_cstr(&match, " && "REGBIT_DNS_LOOKUP_RESULT); >> + ds_put_format(&action, "eth.dst <-> eth.src; ip4.src <-> >> ip4.dst; " >> + "udp.dst = udp.src; udp.src = 53; outport = >> inport; " >> + "flags.loopback = 1; output;"); >> + ovn_lflow_add(lflows, od, S_SWITCH_IN_DNS_RESPONSE, 100, >> + ds_cstr(&match), ds_cstr(&action)); >> + ds_clear(&action); >> + ds_put_format(&action, "eth.dst <-> eth.src; ip6.src <-> >> ip6.dst; " >> + "udp.dst = udp.src; udp.src = 53; outport = >> inport; " >> + "flags.loopback = 1; output;"); >> + ovn_lflow_add(lflows, od, S_SWITCH_IN_DNS_RESPONSE, 100, >> + ds_cstr(&match), ds_cstr(&action)); >> + ds_destroy(&match); >> + ds_destroy(&action); >> + } >> + >> /* Ingress table 11 and 12: DHCP options and response, by default >> goto next. >> - * (priority 0). */ >> + * (priority 0). >> + * Ingress table 13 and 14: DNS lookup and response, by default goto >> next. >> + * (priority 0).*/ >> >> HMAP_FOR_EACH (od, key_node, datapaths) { >> if (!od->nbs) { >> @@ -3313,9 +3367,11 @@ build_lswitch_flows(struct hmap *datapaths, struct >> hmap *ports, >> >> ovn_lflow_add(lflows, od, S_SWITCH_IN_DHCP_OPTIONS, 0, "1", >> "next;"); >> ovn_lflow_add(lflows, od, S_SWITCH_IN_DHCP_RESPONSE, 0, "1", >> "next;"); >> + ovn_lflow_add(lflows, od, S_SWITCH_IN_DNS_LOOKUP, 0, "1", >> "next;"); >> + ovn_lflow_add(lflows, od, S_SWITCH_IN_DNS_RESPONSE, 0, "1", >> "next;"); >> } >> >> - /* Ingress table 13: Destination lookup, broadcast and multicast >> handling >> + /* Ingress table 15: Destination lookup, broadcast and multicast >> handling >> * (priority 100). */ >> HMAP_FOR_EACH (op, key_node, ports) { >> if (!op->nbsp) { >> @@ -5242,6 +5298,87 @@ sync_address_sets(struct northd_context *ctx) >> } >> shash_destroy(&sb_address_sets); >> } >> + >> +static void >> +sync_dns_entries(struct northd_context *ctx, struct hmap *datapaths) >> +{ >> + struct dns_info { >> + struct hmap_node hmap_node; >> + const struct sbrec_datapath_binding *sb; >> + const struct nbrec_dns *dns; >> + }; >> + >> + struct hmap dns_map = HMAP_INITIALIZER(&dns_map); >> + struct ovn_datapath *od; >> + HMAP_FOR_EACH(od, key_node, datapaths) { >> + if (!od->nbs || !od->nbs->n_dns_lookups) { >> + continue; >> + } >> + >> + for (size_t i = 0; i < od->nbs->n_dns_lookups; i++) { >> + struct dns_info *dns_info = xzalloc(sizeof *dns_info); >> + dns_info->sb = od->sb; >> + dns_info->dns = od->nbs->dns_lookups[i]; >> + >> + size_t hash = uuid_hash(&dns_info->sb->header_.uuid); >> + hash = hash_string(dns_info->dns->hostname, hash); >> + hmap_insert(&dns_map, &dns_info->hmap_node, hash); >> + } >> + } >> + >> + const struct sbrec_dns *sbrec_dns, *next; >> + SBREC_DNS_FOR_EACH_SAFE(sbrec_dns, next, ctx->ovnsb_idl) { >> + size_t hash = uuid_hash(&sbrec_dns->datapath->header_.uuid); >> + hash = hash_string(sbrec_dns->hostname, hash); >> + bool delete_dns_record = true; >> + struct dns_info *dns_info; >> + HMAP_FOR_EACH_WITH_HASH(dns_info, hmap_node, hash, &dns_map) { >> + if (!strcmp(dns_info->dns->hostname, sbrec_dns->hostname)) { >> + /* Verify that the IP addresses are same before removing >> from >> + * the hmap. */ >> + if (dns_info->dns->n_ip_addresses != >> + sbrec_dns->n_ip_addresses) { >> + continue; >> + } >> + >> + delete_dns_record = false; >> + for (size_t i = 0; i < sbrec_dns->n_ip_addresses; i++) { >> + if (strcmp(dns_info->dns->ip_addresses[i], >> + sbrec_dns->ip_addresses[i])) { >> + delete_dns_record = true; >> + break; >> + } >> + } >> + >> + if (delete_dns_record) { >> + continue; >> + } >> + >> + hmap_remove(&dns_map, &dns_info->hmap_node); >> + free(dns_info); >> + delete_dns_record = false; >> + break; >> + } >> + } >> + >> + if (delete_dns_record) { >> + sbrec_dns_delete(sbrec_dns); >> + } >> + } >> + >> + struct dns_info *dns_info; >> + HMAP_FOR_EACH_POP(dns_info, hmap_node, &dns_map) { >> + struct sbrec_dns *sbrec_dns = sbrec_dns_insert(ctx->ovnsb_txn); >> + sbrec_dns_set_datapath(sbrec_dns, dns_info->sb); >> + sbrec_dns_set_hostname(sbrec_dns, dns_info->dns->hostname); >> + sbrec_dns_set_ip_addresses( >> + sbrec_dns, (const char **) dns_info->dns->ip_addresses, >> + dns_info->dns->n_ip_addresses); >> + free(dns_info); >> + } >> + hmap_destroy(&dns_map); >> +} >> + >> >> static void >> ovnnb_db_run(struct northd_context *ctx, struct ovsdb_idl_loop *sb_loop) >> @@ -5256,6 +5393,7 @@ ovnnb_db_run(struct northd_context *ctx, struct >> ovsdb_idl_loop *sb_loop) >> build_lflows(ctx, &datapaths, &ports); >> >> sync_address_sets(ctx); >> + sync_dns_entries(ctx, &datapaths); >> >> struct ovn_datapath *dp, *next_dp; >> HMAP_FOR_EACH_SAFE (dp, next_dp, key_node, &datapaths) { >> @@ -5653,6 +5791,10 @@ main(int argc, char *argv[]) >> add_column_noalert(ovnsb_idl_loop.idl, &sbrec_address_set_col_name); >> add_column_noalert(ovnsb_idl_loop.idl, >> &sbrec_address_set_col_addresses); >> >> + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dns); >> + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_datapath); >> + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_hostname); >> + >> ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis); >> ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg); >> >> diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema >> index dd0ac3d..0e97e80 100644 >> --- a/ovn/ovn-nb.ovsschema >> +++ b/ovn/ovn-nb.ovsschema >> @@ -1,7 +1,7 @@ >> { >> "name": "OVN_Northbound", >> - "version": "5.5.0", >> - "cksum": "2099428463 14236", >> + "version": "5.5.1", >> + "cksum": "436648422 14817", >> "tables": { >> "NB_Global": { >> "columns": { >> @@ -45,6 +45,11 @@ >> "refType": "strong"}, >> "min": 0, >> "max": "unlimited"}}, >> + "dns_lookups": {"type": {"key": {"type": "uuid", >> + "refTable": "DNS", >> + "refType": "weak"}, >> + "min": 0, >> + "max": "unlimited"}}, >> "other_config": { >> "type": {"key": "string", "value": "string", >> "min": 0, "max": "unlimited"}}, >> @@ -265,6 +270,13 @@ >> "max": "unlimited"}, >> "ephemeral": true}}, >> "indexes": [["target"]]}, >> + "DNS": { >> + "columns": { >> + "hostname": {"type": "string"}, >> + "ip_addresses": {"type": {"key": "string", >> + "min": 0, >> + "max": "unlimited"}}}, >> + "isRoot": true}, >> > > external_ids would be useful to have too. >
Agree. It was in my mind. I somehow missed it out. > > The above would mean that for each logical port, we need to create a DNS > record in the DNS table. Having the schema like the above has advantages. > In the future, if we have to add new options for DNS, then it becomes > easier to extend this. Do you foresee anything? > I don't foresee any new thing to be added. > > The disadvantage is that for each logical port (or a VIP), you should now > create a new record in DNS table and then link it to all the logical > switches in the logical topology. > > Agree. It results in more work for CMS as it has to manage all this. > An alternate schema would be to have a single DNS record for the logical > topology. i.e have a "record" column which is a map of hostname and > addresses. With this, whenever a new logical port (or a VIP in > load-balancer) is created, you just add the hostname and addresses to the > existing DNS "record" instead of creating a new DNS entry in the table and > linking it all the logical switches in the topology. > > Do you have any opinion? Is one easier than the other for OpenStack? > > The reason I chose to have one DNS record for each logical port as - It almost directly maps to the DNS table in the SB DB (proposed table in patch 1) - the code in ovn-northd would be much simpler at the cost of CMS managing this. I think with the external_ids column, CMS should be able to manage this. - Syncing the NB DNS entries with SB DNS entries would be easier. I personally prefer this approach as it is easier for ovn-northd. But if you think it would be more work for CMS or there are unnecessary ovsdb operations/overhead in having one DNS record per port, I am happy to do the changes as per your suggestions here:). Let me know. Thanks Numan > > > > > >> "SSL": { >> "columns": { >> "private_key": {"type": "string"}, >> diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml >> index 46a25f6..e17fdf6 100644 >> --- a/ovn/ovn-nb.xml >> +++ b/ovn/ovn-nb.xml >> @@ -134,6 +134,11 @@ >> QOS marking rules that apply to packets within the logical switch. >> </column> >> >> + <column name="dns_lookups"> >> + DNS entries to look up for the DNS packets within the logical >> switch >> + by the native DNS resolver. >> + </column> >> + >> <group title="other_config"> >> <p> >> Additional configuration options for the logical switch. >> @@ -1888,6 +1893,20 @@ >> <column name="other_config"/> >> </group> >> </table> >> + <table name="DNS" title="Native DNS resolution"> >> + <p> >> + A DNS look up entry with in a Logical switch. >> + </p> >> + >> + <column name="hostname"> >> + The host name to be searched. >> + </column> >> + >> + <column name="ip_addresses"> >> + The IP addresses to include in the DNS answer fields if the >> + <ref column="hostname"/> matches in the DNS query. >> + </column> >> + </table> >> <table name="SSL"> >> SSL configuration for ovn-nb database access. >> >> @@ -1926,5 +1945,4 @@ >> <column name="external_ids"/> >> </group> >> </table> >> - >> </database> >> diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c >> index 900b088..abdc616 100644 >> --- a/ovn/utilities/ovn-nbctl.c >> +++ b/ovn/utilities/ovn-nbctl.c >> @@ -3048,6 +3048,9 @@ static const struct ctl_table_class >> tables[NBREC_N_TABLES] = { >> >> [NBREC_TABLE_SSL].row_ids[0] >> = {&nbrec_table_nb_global, NULL, &nbrec_nb_global_col_ssl}, >> + >> + [NBREC_TABLE_DNS].row_ids[0] >> + = {&nbrec_table_dns, NULL, &nbrec_dns_col_hostname}, >> }; >> >> static void >> diff --git a/tests/ovn.at b/tests/ovn.at >> index 4b4beb0..3df2e51 100644 >> --- a/tests/ovn.at >> +++ b/tests/ovn.at >> @@ -6334,6 +6334,359 @@ OVS_APP_EXIT_AND_WAIT([ovsdb-server]) >> >> AT_CLEANUP >> >> +AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS]) >> +AT_SKIP_IF([test $HAVE_PYTHON = no]) >> +ovn_start >> + >> +ovn-nbctl ls-add ls1 >> + >> +ovn-nbctl lsp-add ls1 ls1-lp1 \ >> +-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4" >> + >> +ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 >> aef0::4" >> + >> +ovn-nbctl lsp-add ls1 ls1-lp2 \ >> +-- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4" >> + >> +ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 >> 20.0.0.4" >> + >> +LP1_DNS=`ovn-nbctl create DNS hostname=vm1.ovn.org \ >> +ip_addresses="10.0.0.4 aef0\:\:4"` >> + >> +LP2_DNS=`ovn-nbctl create DNS hostname=vm2.ovn.org \ >> +ip_addresses="10.0.0.6 20.0.0.4"` >> + >> +ovn-nbctl add Logical_switch ls1 dns_lookups "$LP1_DNS $LP2_DNS" >> + >> +net_add n1 >> +sim_add hv1 >> + >> +as hv1 >> +ovs-vsctl add-br br-phys >> +ovn_attach n1 br-phys 192.168.0.1 >> +ovs-vsctl -- add-port br-int hv1-vif1 -- \ >> + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ >> + options:tx_pcap=hv1/vif1-tx.pcap \ >> + options:rxq_pcap=hv1/vif1-rx.pcap \ >> + ofport-request=1 >> + >> +ovs-vsctl -- add-port br-int hv1-vif2 -- \ >> + set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \ >> + options:tx_pcap=hv1/vif2-tx.pcap \ >> + options:rxq_pcap=hv1/vif2-rx.pcap \ >> + ofport-request=2 >> + >> +ovn_populate_arp >> +sleep 2 >> +as hv1 ovs-vsctl show >> + >> +echo "*************************" >> +ovn-sbctl list DNS >> +echo "*************************" >> + >> +ip_to_hex() { >> + printf "%02x%02x%02x%02x" "$@" >> +} >> + >> +reset_pcap_file() { >> + local iface=$1 >> + local pcap_file=$2 >> + ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \ >> +options:rxq_pcap=dummy-rx.pcap >> + rm -f ${pcap_file}*.pcap >> + ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap >> \ >> +options:rxq_pcap=${pcap_file}-rx.pcap >> +} >> + >> +# set_lsp_dns_params lsp_name >> +# Sets the dns_req_data and dns_resp_data >> +set_lsp_dns_params() { >> + local lsp_name=$1 >> + local ttl=00000e10 >> + an_count=0001 >> + type=0001 >> + case $lsp_name in >> + ls1-lp1) >> + # vm1.ovn.org >> + hostname=03766d31036f766e036f726700 >> + # IPv4 address - 10.0.0.4 >> + expected_dns_answer=${hostname}00010001${ttl}00040a000004 >> + ;; >> + ls1-lp2) >> + # vm2.ovn.org >> + hostname=03766d32036f766e036f726700 >> + # IPv4 address - 10.0.0.6 >> + expected_dns_answer=${hostname}00010001${ttl}00040a000006 >> + # IPv4 address - 20.0.0.4 >> + expected_dns_answer=${expected_dns_answer}${hostname} >> 00010001${ttl}000414000004 >> + an_count=0002 >> + ;; >> + ls1-lp1_ipv6_only) >> + # vm1.ovn.org >> + hostname=03766d31036f766e036f726700 >> + # IPv6 address - aef0::4 >> + type=001c >> + expected_dns_answer=${hostname}${type}0001${ttl}0010aef00000 >> 000000000000000000000004 >> + ;; >> + ls1-lp1_ipv4_v6) >> + # vm1.ovn.org >> + hostname=03766d31036f766e036f726700 >> + type=00ff >> + an_count=0002 >> + # IPv4 address - 10.0.0.4 >> + # IPv6 address - aef0::4 >> + expected_dns_answer=${hostname}00010001${ttl}00040a000004 >> + expected_dns_answer=${expected_dns_answer}${hostname} >> 001c0001${ttl}0010 >> + expected_dns_answer=${expected_dns_answer}aef000000000000000 >> 00000000000004 >> + ;; >> + ls1-lp1_invalid_type) >> + # vm1.ovn.org >> + hostname=03766d31036f766e036f726700 >> + # IPv6 address - aef0::4 >> + type=0002 >> + ;; >> + ls1-lp1_incomplete) >> + # set type to none >> + type='' >> + esac >> + # TTL - 3600 >> + local dns_req_header=010201200001000000000000 >> + local dns_resp_header=010281200001${an_count}00000000 >> + dns_req_data=${dns_req_header}${hostname}${type}0001 >> + dns_resp_data=${dns_resp_header}${hostname}${type}0001${ >> expected_dns_answer} >> +} >> + >> +# This shell function sends a DNS request packet >> +# test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC >> +test_dns() { >> + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 >> dns_reply=$6 >> + local dns_query_data=$7 >> + shift; shift; shift; shift; shift; shift; shift; >> + # Packet size => IPv4 header (20) + UDP header (8) + >> + # DNS data (header + query) >> + ip_len=`expr 28 + ${#dns_query_data} / 2` >> + udp_len=`expr $ip_len - 20` >> + ip_len=$(printf "%x" $ip_len) >> + udp_len=$(printf "%x" $udp_len) >> + local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110 >> 000 >> + request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000 >> + # dns data >> + request=${request}${dns_query_data} >> + >> + if test $dns_reply != 0; then >> + local dns_reply=$1 >> + ip_len=`expr 28 + ${#dns_reply} / 2` >> + udp_len=`expr $ip_len - 20` >> + ip_len=$(printf "%x" $ip_len) >> + udp_len=$(printf "%x" $udp_len) >> + local reply=${src_mac}${dst_mac}0800 >> 450000${ip_len}0000000080110000 >> + reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dn >> s_reply} >> + echo $reply >> $inport.expected >> + else >> + for outport; do >> + echo $request >> $outport.expected >> + done >> + fi >> + as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request >> +} >> + >> +AT_CAPTURE_FILE([ofctl_monitor0.log]) >> +as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \ >> +--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log >> + >> +set_lsp_dns_params ls1-lp2 >> +src_ip=`ip_to_hex 10 0 0 4` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=1 >> +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply >> $dns_req_data $dns_resp_data >> + >> +# NXT_RESUMEs should be 1. >> +OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets >> +cat 1.expected | cut -c -48 > expout >> +AT_CHECK([cat 1.packets | cut -c -48], [0], [expout]) >> +# Skipping the IPv4 checksum. >> +cat 1.expected | cut -c 53- > expout >> +AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout]) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +set_lsp_dns_params ls1-lp1 >> +src_ip=`ip_to_hex 10 0 0 6` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=1 >> +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply >> $dns_req_data $dns_resp_data >> + >> +# NXT_RESUMEs should be 2. >> +OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets >> +cat 2.expected | cut -c -48 > expout >> +AT_CHECK([cat 2.packets | cut -c -48], [0], [expout]) >> +# Skipping the IPv4 checksum. >> +cat 2.expected | cut -c 53- > expout >> +AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout]) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +# Clear the hostname options for ls1-lp2 >> +ovn-nbctl --wait=hv clear Logical_switch ls1 dns_lookups >> +ovn-nbctl --wait=hv add Logical_switch ls1 dns_lookups $LP1_DNS >> + >> +ovn-nbctl list logical_switch >> +echo "****************" >> +ovn-nbctl list DNS >> +echo "****************" >> +ovn-sbctl list DNS >> +echo "**********" >> + >> +set_lsp_dns_params ls1-lp2 >> +src_ip=`ip_to_hex 10 0 0 4` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=0 >> +test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply >> $dns_req_data >> + >> +# NXT_RESUMEs should be 3. >> +OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets >> +AT_CHECK([cat 1.packets], [0], []) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +# Clear the hostname for ls1-lp1 >> +# Since no ports of ls1 has hostname configued, >> +# ovn-northd should not add the DNS flows. >> +ovn-nbctl clear Logical_switch ls1 dns_lookups >> +set_lsp_dns_params ls1-lp1 >> +src_ip=`ip_to_hex 10 0 0 6` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=0 >> +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply >> $dns_req_data >> + >> +# NXT_RESUMEs should be 3 only. >> +OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets >> +AT_CHECK([cat 2.packets], [0], []) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +# Test IPv6 (AAAA records) using IPv4 packet. >> +# Add back the DNS options for ls1-lp1. >> +ovn-nbctl add Logical_switch ls1 dns_lookups $LP1_DNS >> + >> +set_lsp_dns_params ls1-lp1_ipv6_only >> +src_ip=`ip_to_hex 10 0 0 6` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=1 >> +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply >> $dns_req_data $dns_resp_data >> + >> +# NXT_RESUMEs should be 4. >> +OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets >> +cat 2.expected | cut -c -48 > expout >> +AT_CHECK([cat 2.packets | cut -c -48], [0], [expout]) >> +# Skipping the IPv4 checksum. >> +cat 2.expected | cut -c 53- > expout >> +AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout]) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet. >> +set_lsp_dns_params ls1-lp1_ipv4_v6 >> +src_ip=`ip_to_hex 10 0 0 6` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=1 >> +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply >> $dns_req_data $dns_resp_data >> + >> +# NXT_RESUMEs should be 5. >> +OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets >> +cat 2.expected | cut -c -48 > expout >> +AT_CHECK([cat 2.packets | cut -c -48], [0], [expout]) >> +# Skipping the IPv4 checksum. >> +cat 2.expected | cut -c 53- > expout >> +AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout]) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +# Invalid type. >> +set_lsp_dns_params ls1-lp1_invalid_type >> +src_ip=`ip_to_hex 10 0 0 6` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=0 >> +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply >> $dns_req_data >> + >> +# NXT_RESUMEs should be 6. >> +OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets >> +AT_CHECK([cat 2.packets], [0], []) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +# Incomplete DNS packet. >> +set_lsp_dns_params ls1-lp1_incomplete >> +src_ip=`ip_to_hex 10 0 0 6` >> +dst_ip=`ip_to_hex 10 0 0 1` >> +dns_reply=0 >> +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply >> $dns_req_data >> + >> +# NXT_RESUMEs should be 7. >> +OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) >> + >> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets >> +AT_CHECK([cat 2.packets], [0], []) >> + >> +reset_pcap_file hv1-vif1 hv1/vif1 >> +reset_pcap_file hv1-vif2 hv1/vif2 >> +rm -f 1.expected >> +rm -f 2.expected >> + >> +as hv1 >> +OVS_APP_EXIT_AND_WAIT([ovn-controller]) >> +OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) >> + >> +as ovn-sb >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) >> + >> +as ovn-nb >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) >> + >> +as northd >> +OVS_APP_EXIT_AND_WAIT([ovn-northd]) >> + >> +as main >> +OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) >> +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) >> +AT_CLEANUP >> + >> AT_SETUP([ovn -- 1 LR with distributed router gateway port]) >> AT_SKIP_IF([test $HAVE_PYTHON = no]) >> ovn_start >> -- >> 2.9.3 >> >> _______________________________________________ >> dev mailing list >> d...@openvswitch.org >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> > > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev