mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 18:42:23 +00:00
Merge pull request #4812 from pogojotz/fix-destination-multi-use
zebra: Do not use connection dest for bcast
This commit is contained in:
commit
dec2a1469f
6
lib/if.h
6
lib/if.h
@ -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. */
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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 *);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user