Merge pull request #4812 from pogojotz/fix-destination-multi-use

zebra: Do not use connection dest for bcast
This commit is contained in:
Donald Sharp 2019-08-26 09:25:17 -04:00 committed by GitHub
commit dec2a1469f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 125 deletions

View File

@ -383,16 +383,12 @@ struct connected {
/* N.B. the ZEBRA_IFA_PEER flag should be set if and only if
a peer address has been configured. If this flag is set,
the destination field must contain the peer address.
Otherwise, if this flag is not set, the destination address
will either contain a broadcast address or be NULL.
*/
/* Address of connected network. */
struct prefix *address;
/* Peer or Broadcast address, depending on whether ZEBRA_IFA_PEER is
set.
Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */
/* Peer address, if ZEBRA_IFA_PEER is set, otherwise NULL */
struct prefix *destination;
/* Label for Linux 2.2.X and upper. */

View File

@ -3442,6 +3442,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
else
vty_out(vty, " This interface is UNNUMBERED,");
} else {
struct in_addr dest;
const char *dstr;
/* Show OSPF interface information. */
if (use_json) {
json_object_string_add(
@ -3455,46 +3458,40 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
inet_ntoa(oi->address->u.prefix4),
oi->address->prefixlen);
if (oi->connected->destination
|| oi->type == OSPF_IFTYPE_VIRTUALLINK) {
struct in_addr *dest;
const char *dstr;
/* For Vlinks, showing the peer address is
* probably more informative than the local
* interface that is being used */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK) {
dstr = "Peer";
dest = oi->vl_data->peer_addr;
} else if (CONNECTED_PEER(oi->connected)
&& oi->connected->destination) {
dstr = "Peer";
dest = oi->connected->destination->u.prefix4;
} else {
dstr = "Broadcast";
dest.s_addr = ipv4_broadcast_addr(
oi->connected->address->u.prefix4.s_addr,
oi->connected->address->prefixlen);
}
if (CONNECTED_PEER(oi->connected)
|| oi->type == OSPF_IFTYPE_VIRTUALLINK)
dstr = "Peer";
else
dstr = "Broadcast";
/* For Vlinks, showing the peer address is
* probably more
* * * * * informative than the local
* interface that is being used
* * * * */
if (use_json) {
json_object_string_add(
json_interface_sub,
"ospfIfType", dstr);
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
dest = &oi->vl_data->peer_addr;
else
dest = &oi->connected->destination->u
.prefix4;
if (use_json) {
json_object_string_add(
json_interface_sub,
"ospfIfType", dstr);
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
json_object_string_add(
json_interface_sub,
"vlinkPeer",
inet_ntoa(*dest));
else
json_object_string_add(
json_interface_sub,
"localIfUsed",
inet_ntoa(*dest));
} else
vty_out(vty, " %s %s,", dstr,
inet_ntoa(*dest));
}
"vlinkPeer",
inet_ntoa(dest));
else
json_object_string_add(
json_interface_sub,
"localIfUsed",
inet_ntoa(dest));
} else
vty_out(vty, " %s %s,", dstr,
inet_ntoa(dest));
}
if (use_json) {
json_object_string_add(json_interface_sub, "area",

View File

@ -120,10 +120,6 @@ struct connected *connected_check_ptp(struct interface *ifp,
struct connected *ifc;
struct listnode *node;
/* ignore broadcast addresses */
if (p->prefixlen != IPV4_MAX_PREFIXLEN)
d = NULL;
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
if (!prefix_same(ifc->address, p))
continue;
@ -143,6 +139,12 @@ static int connected_same(struct connected *ifc1, struct connected *ifc2)
if (ifc1->ifp != ifc2->ifp)
return 0;
if (ifc1->flags != ifc2->flags)
return 0;
if (ifc1->conf != ifc2->conf)
return 0;
if (ifc1->destination)
if (!ifc2->destination)
return 0;
@ -154,12 +156,6 @@ static int connected_same(struct connected *ifc1, struct connected *ifc2)
if (!prefix_same(ifc1->destination, ifc2->destination))
return 0;
if (ifc1->flags != ifc2->flags)
return 0;
if (ifc1->conf != ifc2->conf)
return 0;
return 1;
}
@ -276,7 +272,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
/* Add connected IPv4 route to the interface. */
void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
uint16_t prefixlen, struct in_addr *broad,
uint16_t prefixlen, struct in_addr *dest,
const char *label, uint32_t metric)
{
struct prefix_ipv4 *p;
@ -302,59 +298,39 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
: prefixlen;
ifc->address = (struct prefix *)p;
/* If there is broadcast or peer address. */
if (broad) {
p = prefix_ipv4_new();
p->family = AF_INET;
p->prefix = *broad;
p->prefixlen = prefixlen;
ifc->destination = (struct prefix *)p;
/* If there is a peer address. */
if (CONNECTED_PEER(ifc)) {
/* validate the destination address */
if (CONNECTED_PEER(ifc)) {
if (IPV4_ADDR_SAME(addr, broad))
if (dest) {
p = prefix_ipv4_new();
p->family = AF_INET;
p->prefix = *dest;
p->prefixlen = prefixlen;
ifc->destination = (struct prefix *)p;
if (IPV4_ADDR_SAME(addr, dest))
flog_warn(
EC_ZEBRA_IFACE_SAME_LOCAL_AS_PEER,
"warning: interface %s has same local and peer "
"address %s, routing protocols may malfunction",
ifp->name, inet_ntoa(*addr));
} else {
if (broad->s_addr
!= ipv4_broadcast_addr(addr->s_addr, prefixlen)) {
char buf[2][INET_ADDRSTRLEN];
struct in_addr bcalc;
bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,
prefixlen);
flog_warn(
EC_ZEBRA_BCAST_ADDR_MISMATCH,
"warning: interface %s broadcast addr %s/%d != "
"calculated %s, routing protocols may malfunction",
ifp->name,
inet_ntop(AF_INET, broad, buf[0],
sizeof(buf[0])),
prefixlen,
inet_ntop(AF_INET, &bcalc, buf[1],
sizeof(buf[1])));
}
}
} else {
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
zlog_debug(
"warning: %s called for interface %s "
"with peer flag set, but no peer address supplied",
__func__, ifp->name);
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
}
/* no broadcast or destination address was supplied */
if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
zlog_debug(
"warning: PtP interface %s with addr %s/%d needs a "
"peer address",
ifp->name, inet_ntoa(*addr), prefixlen);
}
/* no destination address was supplied */
if (!dest && (prefixlen == IPV4_MAX_PREFIXLEN)
&& if_is_pointopoint(ifp))
zlog_debug(
"warning: PtP interface %s with addr %s/%d needs a "
"peer address",
ifp->name, inet_ntoa(*addr), prefixlen);
/* Label of this address. */
if (label)
ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
@ -464,7 +440,7 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p)
/* Delete connected IPv4 route to the interface. */
void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
struct in_addr *broad)
struct in_addr *dest)
{
struct prefix p, d;
struct connected *ifc;
@ -475,10 +451,10 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
: prefixlen;
if (broad) {
if (dest) {
memset(&d, 0, sizeof(struct prefix));
d.family = AF_INET;
d.u.prefix4 = *broad;
d.u.prefix4 = *dest;
d.prefixlen = prefixlen;
ifc = connected_check_ptp(ifp, &p, &d);
} else
@ -489,7 +465,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
/* Add connected IPv6 route to the interface. */
void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
struct in6_addr *broad, uint16_t prefixlen,
struct in6_addr *dest, uint16_t prefixlen,
const char *label, uint32_t metric)
{
struct prefix_ipv6 *p;
@ -514,10 +490,10 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
p->prefixlen = prefixlen;
ifc->address = (struct prefix *)p;
if (broad) {
if (dest) {
p = prefix_ipv6_new();
p->family = AF_INET6;
IPV6_ADDR_COPY(&p->prefix, broad);
IPV6_ADDR_COPY(&p->prefix, dest);
p->prefixlen = prefixlen;
ifc->destination = (struct prefix *)p;
} else {
@ -547,7 +523,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
}
void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
struct in6_addr *broad, uint16_t prefixlen)
struct in6_addr *dest, uint16_t prefixlen)
{
struct prefix p, d;
struct connected *ifc;
@ -557,10 +533,10 @@ void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
memcpy(&p.u.prefix6, address, sizeof(struct in6_addr));
p.prefixlen = prefixlen;
if (broad) {
if (dest) {
memset(&d, 0, sizeof(struct prefix));
d.family = AF_INET6;
IPV6_ADDR_COPY(&d.u.prefix6, broad);
IPV6_ADDR_COPY(&d.u.prefix6, dest);
d.prefixlen = prefixlen;
ifc = connected_check_ptp(ifp, &p, &d);
} else

View File

@ -40,12 +40,12 @@ extern struct connected *connected_check_ptp(struct interface *ifp,
extern void connected_add_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
struct in_addr *broad, const char *label,
struct in_addr *dest, const char *label,
uint32_t metric);
extern void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
struct in_addr *broad);
struct in_addr *dest);
extern void connected_delete_ipv4_unnumbered(struct connected *ifc);
@ -53,12 +53,12 @@ extern void connected_up(struct interface *ifp, struct connected *ifc);
extern void connected_down(struct interface *ifp, struct connected *ifc);
extern void connected_add_ipv6(struct interface *ifp, int flags,
struct in6_addr *address, struct in6_addr *broad,
struct in6_addr *address, struct in6_addr *dest,
uint16_t prefixlen, const char *label,
uint32_t metric);
extern void connected_delete_ipv6(struct interface *ifp,
struct in6_addr *address,
struct in6_addr *broad, uint16_t prefixlen);
struct in6_addr *dest, uint16_t prefixlen);
extern int connected_is_unnumbered(struct interface *);

View File

@ -888,11 +888,13 @@ static int netlink_address_ctx(const struct zebra_dplane_ctx *ctx)
p = dplane_ctx_get_intf_dest(ctx);
addattr_l(&req.n, sizeof(req), IFA_ADDRESS,
&p->u.prefix, bytelen);
} else if (cmd == RTM_NEWADDR &&
dplane_ctx_intf_has_dest(ctx)) {
p = dplane_ctx_get_intf_dest(ctx);
} else if (cmd == RTM_NEWADDR) {
struct in_addr broad = {
.s_addr = ipv4_broadcast_addr(p->u.prefix4.s_addr,
p->prefixlen)
};
addattr_l(&req.n, sizeof(req), IFA_BROADCAST,
&p->u.prefix, bytelen);
&broad, bytelen);
}
}
@ -1065,7 +1067,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
else
connected_delete_ipv4(
ifp, flags, (struct in_addr *)addr,
ifa->ifa_prefixlen, (struct in_addr *)broad);
ifa->ifa_prefixlen, NULL);
}
if (ifa->ifa_family == AF_INET6) {
if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) {
@ -1091,8 +1093,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
metric);
} else
connected_delete_ipv6(ifp, (struct in6_addr *)addr,
(struct in6_addr *)broad,
ifa->ifa_prefixlen);
NULL, ifa->ifa_prefixlen);
}
return 0;

View File

@ -1081,12 +1081,10 @@ static void connected_dump_vty(struct vty *vty, struct connected *connected)
vty_out(vty, "/%d", p->prefixlen);
/* If there is destination address, print it. */
if (connected->destination) {
vty_out(vty,
(CONNECTED_PEER(connected) ? " peer " : " broadcast "));
if (CONNECTED_PEER(connected) && connected->destination) {
vty_out(vty, " peer ");
prefix_vty_out(vty, connected->destination);
if (CONNECTED_PEER(connected))
vty_out(vty, "/%d", connected->destination->prefixlen);
vty_out(vty, "/%d", connected->destination->prefixlen);
}
if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
@ -2684,12 +2682,6 @@ static int ip_address_install(struct vty *vty, struct interface *ifp,
p = prefix_ipv4_new();
*p = pp;
ifc->destination = (struct prefix *)p;
} else if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) {
p = prefix_ipv4_new();
*p = lp;
p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,
p->prefixlen);
ifc->destination = (struct prefix *)p;
}
/* Label. */

View File

@ -134,7 +134,7 @@ struct dplane_intf_info {
#define DPLANE_INTF_CONNECTED (1 << 0) /* Connected peer, p2p */
#define DPLANE_INTF_SECONDARY (1 << 1)
#define DPLANE_INTF_BROADCAST (1 << 2)
#define DPLANE_INTF_HAS_DEST (1 << 3)
#define DPLANE_INTF_HAS_DEST DPLANE_INTF_CONNECTED
#define DPLANE_INTF_HAS_LABEL (1 << 4)
/* Interface address/prefix */
@ -2022,9 +2022,6 @@ static enum zebra_dplane_result intf_addr_update_internal(
ctx->u.intf.dest_prefix = *(ifc->destination);
ctx->u.intf.flags |=
(DPLANE_INTF_CONNECTED | DPLANE_INTF_HAS_DEST);
} else if (ifc->destination) {
ctx->u.intf.dest_prefix = *(ifc->destination);
ctx->u.intf.flags |= DPLANE_INTF_HAS_DEST;
}
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))