sctp: add SCTP_ADDR_ADDED event

A helper sctp_ulpevent_nofity_peer_addr_change() will be extracted
to make peer_addr_change event and enqueue it, and the helper will
be called in sctp_assoc_add_peer() to send SCTP_ADDR_ADDED event.

This event is described in rfc6458#section-6.1.2:

  SCTP_ADDR_ADDED:  The address is now part of the association.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
This commit is contained in:
Xin Long 2019-10-08 19:27:33 +08:00 committed by Jakub Kicinski
parent 7579262478
commit 4b7740324e
3 changed files with 25 additions and 21 deletions

View File

@ -80,13 +80,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
struct sctp_chunk *chunk,
gfp_t gfp);
struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
const struct sctp_association *asoc,
const struct sockaddr_storage *aaddr,
int flags,
int state,
int error,
gfp_t gfp);
void sctp_ulpevent_nofity_peer_addr_change(struct sctp_transport *transport,
int state, int error);
struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
const struct sctp_association *asoc,

View File

@ -707,6 +707,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
asoc->peer.transport_count++;
sctp_ulpevent_nofity_peer_addr_change(peer, SCTP_ADDR_ADDED, 0);
/* If we do not yet have a primary path, set one. */
if (!asoc->peer.primary_path) {
sctp_assoc_set_primary(asoc, peer);
@ -781,10 +783,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
enum sctp_transport_cmd command,
sctp_sn_error_t error)
{
struct sctp_ulpevent *event;
struct sockaddr_storage addr;
int spc_state = 0;
bool ulp_notify = true;
int spc_state = 0;
/* Record the transition on the transport. */
switch (command) {
@ -836,16 +836,9 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
/* Generate and send a SCTP_PEER_ADDR_CHANGE notification
* to the user.
*/
if (ulp_notify) {
memset(&addr, 0, sizeof(struct sockaddr_storage));
memcpy(&addr, &transport->ipaddr,
transport->af_specific->sockaddr_len);
event = sctp_ulpevent_make_peer_addr_change(asoc, &addr,
0, spc_state, error, GFP_ATOMIC);
if (event)
asoc->stream.si->enqueue_event(&asoc->ulpq, event);
}
if (ulp_notify)
sctp_ulpevent_nofity_peer_addr_change(transport,
spc_state, error);
/* Select new active and retran paths. */
sctp_select_active_and_retran_path(asoc);

View File

@ -238,7 +238,7 @@ fail:
* When a destination address on a multi-homed peer encounters a change
* an interface details event is sent.
*/
struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
static struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
const struct sctp_association *asoc,
const struct sockaddr_storage *aaddr,
int flags, int state, int error, gfp_t gfp)
@ -336,6 +336,22 @@ fail:
return NULL;
}
void sctp_ulpevent_nofity_peer_addr_change(struct sctp_transport *transport,
int state, int error)
{
struct sctp_association *asoc = transport->asoc;
struct sockaddr_storage addr;
struct sctp_ulpevent *event;
memset(&addr, 0, sizeof(struct sockaddr_storage));
memcpy(&addr, &transport->ipaddr, transport->af_specific->sockaddr_len);
event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, 0, state,
error, GFP_ATOMIC);
if (event)
asoc->stream.si->enqueue_event(&asoc->ulpq, event);
}
/* Create and initialize an SCTP_REMOTE_ERROR notification.
*
* Note: This assumes that the chunk->skb->data already points to the