This patch sets up the primitive functions to pass on struct net in preparation for SCTP to use per-net protocol parameters. Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx> --- include/net/sctp/sctp.h | 15 ++++++++------ include/net/sctp/sm.h | 6 ++++-- net/sctp/associola.c | 3 ++- net/sctp/endpointola.c | 4 ++-- net/sctp/input.c | 2 +- net/sctp/primitive.c | 4 ++-- net/sctp/sm_sideeffect.c | 51 ++++++++++++++++++---------------------------- net/sctp/sm_statetable.c | 3 ++- net/sctp/socket.c | 41 ++++++++++++++++++++----------------- 9 files changed, 64 insertions(+), 65 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index eb2ec98..8488d5e 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -146,12 +146,15 @@ extern int sctp_asconf_mgmt(struct net *, struct sctp_sock *, /* * sctp/primitive.c */ -int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg); -int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg); -int sctp_primitive_ABORT(struct sctp_association *, void *arg); -int sctp_primitive_SEND(struct sctp_association *, void *arg); -int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg); -int sctp_primitive_ASCONF(struct sctp_association *, void *arg); +int sctp_primitive_ASSOCIATE(struct net *, struct sctp_association *, + void *arg); +int sctp_primitive_SHUTDOWN(struct net *, struct sctp_association *, + void *arg); +int sctp_primitive_ABORT(struct net *, struct sctp_association *, void *arg); +int sctp_primitive_SEND(struct net *, struct sctp_association *, void *arg); +int sctp_primitive_REQUESTHEARTBEAT(struct net *, struct sctp_association *, + void *arg); +int sctp_primitive_ASCONF(struct net *, struct sctp_association *, void *arg); /* * sctp/input.c diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index a83ce1b..8b1a4a6 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -179,7 +179,8 @@ sctp_state_fn_t sctp_sf_autoclose_timer_expire; /* Prototypes for utility support functions. */ __u8 sctp_get_chunk_type(struct sctp_chunk *chunk); -const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t, +const sctp_sm_table_entry_t *sctp_sm_lookup_event(struct net *, + sctp_event_t, sctp_state_t, sctp_subtype_t); int sctp_chunk_iif(const struct sctp_chunk *); @@ -269,7 +270,8 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *); /* Prototypes for statetable processing. */ -int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, +int sctp_do_sm(struct net *, + sctp_event_t event_type, sctp_subtype_t subtype, sctp_state_t state, struct sctp_endpoint *, struct sctp_association *asoc, diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 001f44b..1bd956b 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1123,6 +1123,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) int state; sctp_subtype_t subtype; int error = 0; + struct net *net = sock_net(asoc->base.sk); /* The association should be held so we should be safe. */ ep = asoc->ep; @@ -1155,7 +1156,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) chunk->transport->last_time_heard = jiffies; /* Run through the state machine. */ - error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, + error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state, ep, asoc, chunk, GFP_ATOMIC); /* Check to see if the association is freed in response to diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 68a385d..de42bd4 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -479,8 +479,8 @@ normal: if (chunk->transport) chunk->transport->last_time_heard = jiffies; - error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state, - ep, asoc, chunk, GFP_ATOMIC); + error = sctp_do_sm(sock_net(sk), SCTP_EVENT_T_CHUNK, subtype, + state, ep, asoc, chunk, GFP_ATOMIC); if (error && chunk) chunk->pdiscard = 1; diff --git a/net/sctp/input.c b/net/sctp/input.c index fc94829..1b92da2 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -466,7 +466,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, del_timer(&t->proto_unreach_timer)) sctp_association_put(asoc); - sctp_do_sm(SCTP_EVENT_T_OTHER, + sctp_do_sm(sock_net(sk), SCTP_EVENT_T_OTHER, SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), asoc->state, asoc->ep, asoc, t, GFP_ATOMIC); diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index 534c7ea..a84a602 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -57,7 +57,7 @@ #define DECLARE_PRIMITIVE(name) \ /* This is called in the code as sctp_primitive_ ## name. */ \ -int sctp_primitive_ ## name(struct sctp_association *asoc, \ +int sctp_primitive_ ## name(struct net *net, struct sctp_association *asoc, \ void *arg) { \ int error = 0; \ sctp_event_t event_type; sctp_subtype_t subtype; \ @@ -69,7 +69,7 @@ int sctp_primitive_ ## name(struct sctp_association *asoc, \ state = asoc ? asoc->state : SCTP_STATE_CLOSED; \ ep = asoc ? asoc->ep : NULL; \ \ - error = sctp_do_sm(event_type, subtype, state, ep, asoc, \ + error = sctp_do_sm(net, event_type, subtype, state, ep, asoc, \ arg, GFP_KERNEL); \ return error; \ } diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 529e3e4..2c895fd 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -63,6 +63,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sctp_state_t state, struct sctp_endpoint *ep, struct sctp_association *asoc, + struct net *net, void *event_arg, sctp_disposition_t status, sctp_cmd_seq_t *commands, @@ -252,6 +253,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer) int error; struct sctp_transport *transport = (struct sctp_transport *) peer; struct sctp_association *asoc = transport->asoc; + struct net *net = sock_net(asoc->base.sk); /* Check whether a task is in the sock. */ @@ -272,7 +274,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer) goto out_unlock; /* Run through the state machine. */ - error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT, + error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_T3_RTX), asoc->state, asoc->ep, asoc, @@ -313,7 +315,7 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc, goto out_unlock; /* Run through the state machine. */ - error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT, + error = sctp_do_sm(sock_net(asoc->base.sk), SCTP_EVENT_T_TIMEOUT, SCTP_ST_TIMEOUT(timeout_type), asoc->state, asoc->ep, asoc, (void *)timeout_type, GFP_ATOMIC); @@ -389,7 +391,7 @@ void sctp_generate_heartbeat_event(unsigned long data) if (transport->dead) goto out_unlock; - error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT, + error = sctp_do_sm(sock_net(asoc->base.sk), SCTP_EVENT_T_TIMEOUT, SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_HEARTBEAT), asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); @@ -427,7 +429,7 @@ void sctp_generate_proto_unreach_event(unsigned long data) if (asoc->base.dead) goto out_unlock; - sctp_do_sm(SCTP_EVENT_T_OTHER, + sctp_do_sm(sock_net(asoc->base.sk), SCTP_EVENT_T_OTHER, SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); @@ -603,7 +605,8 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands, * since all other cases use "temporary" associations and can do all * their work in statefuns directly. */ -static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, +static int sctp_cmd_process_init(struct net *net, + sctp_cmd_seq_t *commands, struct sctp_association *asoc, struct sctp_chunk *chunk, sctp_init_chunk_t *peer_init, @@ -617,7 +620,7 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, * just return the error and stop processing the stack. */ if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init, - &init_net, gfp)) + net, gfp)) error = -ENOMEM; else error = 0; @@ -756,7 +759,7 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, if (sctp_outq_sack(&asoc->outqueue, sackh)) { /* There are no more TSNs awaiting SACK. */ - err = sctp_do_sm(SCTP_EVENT_T_OTHER, + err = sctp_do_sm(sock_net(asoc->base.sk), SCTP_EVENT_T_OTHER, SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), asoc->state, asoc->ep, asoc, NULL, GFP_ATOMIC); @@ -1055,7 +1058,8 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc) /* Hold the chunk until an ASCONF_ACK is received. */ sctp_chunk_hold(asconf); - if (sctp_primitive_ASCONF(asoc, asconf)) + if (sctp_primitive_ASCONF(sock_net(asoc->base.sk), asoc, + asconf)) sctp_chunk_free(asconf); else asoc->addip_last_asconf = asconf; @@ -1091,7 +1095,8 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc) * If you want to understand all of lksctp, this is a * good place to start. */ -int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, +int sctp_do_sm(struct net *net, sctp_event_t event_type, + sctp_subtype_t subtype, sctp_state_t state, struct sctp_endpoint *ep, struct sctp_association *asoc, @@ -1107,31 +1112,13 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, static printfn_t *table[] = { NULL, sctp_cname, sctp_tname, sctp_oname, sctp_pname, }; - struct net *net; printfn_t *debug_fn __attribute__ ((unused)) = table[event_type]; - /* The following is a temporary kludge. It'll be fixed in the next - * patch. We need struct net to pass to the various - * sctp_disposition_t functions, so Check if there's struct net - * information in the association, if not, get the information - * from the endpoint. - */ - if ((ep) && (&ep->base) && (ep->base.sk) && - (ep->base.sk->sk_net)) { - net = sock_net(ep->base.sk); - } else { - if ((asoc) && (&asoc->base) && (asoc->base.sk) - && (asoc->base.sk->sk_net)) { - net = sock_net(asoc->base.sk); - } else - net = &init_net; - } - /* Look up the state function, run it, and then process the * side effects. These three steps are the heart of lksctp. */ - state_fn = sctp_sm_lookup_event(event_type, state, subtype); + state_fn = sctp_sm_lookup_event(net, event_type, state, subtype); sctp_init_cmd_seq(&commands); @@ -1172,7 +1159,7 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, * disposition SCTP_DISPOSITION_CONSUME. */ if (0 != (error = sctp_cmd_interpreter(event_type, subtype, state, - ep, asoc, + ep, asoc, net, event_arg, status, commands, gfp))) goto bail; @@ -1243,6 +1230,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sctp_state_t state, struct sctp_endpoint *ep, struct sctp_association *asoc, + struct net *net, void *event_arg, sctp_disposition_t status, sctp_cmd_seq_t *commands, @@ -1365,8 +1353,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, * there is an error just return to the outter * layer which will bail. */ - error = sctp_cmd_process_init(commands, asoc, chunk, - cmd->obj.ptr, gfp); + error = sctp_cmd_process_init(net, commands, asoc, + chunk, cmd->obj.ptr, + gfp); break; case SCTP_CMD_GEN_COOKIE_ECHO: diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 7c211a7..c249e59 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -82,7 +82,8 @@ static const sctp_sm_table_entry_t bug = { rtn; \ }) -const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, +const sctp_sm_table_entry_t *sctp_sm_lookup_event(struct net *net, + sctp_event_t event_type, sctp_state_t state, sctp_subtype_t event_subtype) { diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 790e597..78e4576 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -211,6 +211,8 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id) { struct sctp_association *asoc = NULL; + struct sctp_ns_globals *ns_globals = + sctp_get_ns_globals(sock_net(sk)); /* If this is not a UDP-style socket, assoc id should be ignored. */ if (!sctp_style(sk, UDP)) { @@ -232,9 +234,10 @@ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id) if (!id || (id == (sctp_assoc_t)-1)) return NULL; - spin_lock_bh(&sctp_assocs_id_lock); - asoc = (struct sctp_association *)idr_find(&sctp_assocs_id, (int)id); - spin_unlock_bh(&sctp_assocs_id_lock); + spin_lock_bh(&ns_globals->assocs_id_lock); + asoc = (struct sctp_association *)idr_find(&ns_globals->assocs_id, + (int)id); + spin_unlock_bh(&ns_globals->assocs_id_lock); if (!asoc || (asoc->base.sk != sk) || asoc->base.dead) return NULL; @@ -441,7 +444,7 @@ static int sctp_send_asconf(struct sctp_association *asoc, /* Hold the chunk until an ASCONF_ACK is received. */ sctp_chunk_hold(chunk); - retval = sctp_primitive_ASCONF(asoc, chunk); + retval = sctp_primitive_ASCONF(sock_net(asoc->base.sk), asoc, chunk); if (retval) sctp_chunk_free(chunk); else @@ -1179,8 +1182,8 @@ static int __sctp_connect(struct sock* sk, } err = sctp_assoc_set_bind_addr_from_ep(asoc, - sock_net(sk), - scope, GFP_KERNEL); + sock_net(sk), scope, + GFP_KERNEL); if (err < 0) { goto out_free; } @@ -1209,7 +1212,7 @@ static int __sctp_connect(struct sock* sk, goto out_free; } - err = sctp_primitive_ASSOCIATE(asoc, NULL); + err = sctp_primitive_ASSOCIATE(sock_net(sk), asoc, NULL); if (err < 0) { goto out_free; } @@ -1508,9 +1511,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) chunk = sctp_make_abort_user(asoc, NULL, 0); if (chunk) - sctp_primitive_ABORT(asoc, chunk); + sctp_primitive_ABORT(sock_net(sk), asoc, chunk); } else - sctp_primitive_SHUTDOWN(asoc, NULL); + sctp_primitive_SHUTDOWN(sock_net(sk), asoc, NULL); } /* On a TCP-style socket, block for at most linger_time if set. */ @@ -1723,7 +1726,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, if (sinfo_flags & SCTP_EOF) { SCTP_DEBUG_PRINTK("Shutting down association: %p\n", asoc); - sctp_primitive_SHUTDOWN(asoc, NULL); + sctp_primitive_SHUTDOWN(sock_net(sk), asoc, NULL); err = 0; goto out_unlock; } @@ -1736,7 +1739,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); - sctp_primitive_ABORT(asoc, chunk); + sctp_primitive_ABORT(sock_net(sk), asoc, chunk); err = 0; goto out_unlock; } @@ -1910,7 +1913,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* Auto-connect, if we aren't connected already. */ if (sctp_state(asoc, CLOSED)) { - err = sctp_primitive_ASSOCIATE(asoc, NULL); + err = sctp_primitive_ASSOCIATE(sock_net(sk), asoc, NULL); if (err < 0) goto out_free; SCTP_DEBUG_PRINTK("We associated primitively.\n"); @@ -1938,7 +1941,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, * works that way today. Keep it that way or this * breaks. */ - err = sctp_primitive_SEND(asoc, datamsg); + err = sctp_primitive_SEND(sock_net(sk), asoc, datamsg); /* Did the lower layer accept the chunk? */ if (err) sctp_datamsg_free(datamsg); @@ -2331,7 +2334,8 @@ static int sctp_apply_peer_addr_params(struct net *net, int error; if (params->spp_flags & SPP_HB_DEMAND && trans) { - error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans); + error = sctp_primitive_REQUESTHEARTBEAT(net, trans->asoc, + trans); if (error) return error; } @@ -2398,7 +2402,8 @@ static int sctp_apply_peer_addr_params(struct net *net, int update = (trans->param_flags & SPP_PMTUD_DISABLE) && (params->spp_flags & SPP_PMTUD_ENABLE); trans->param_flags = - (trans->param_flags & ~SPP_PMTUD) | pmtud_change; + (trans->param_flags & ~SPP_PMTUD) | + pmtud_change; if (update) { sctp_transport_pmtu(net, trans, sctp_opt2sk(sp)); @@ -4035,7 +4040,7 @@ SCTP_STATIC void sctp_shutdown(struct sock *sk, int how) if (!list_empty(&ep->asocs)) { asoc = list_entry(ep->asocs.next, struct sctp_association, asocs); - sctp_primitive_SHUTDOWN(asoc, NULL); + sctp_primitive_SHUTDOWN(sock_net(sk), asoc, NULL); } } } @@ -4666,11 +4671,9 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, union sctp_addr temp; int cnt = 0; int addrlen; - struct sctp_net_params *net_params = - sctp_get_params(sock_net(sk)); rcu_read_lock(); - list_for_each_entry_rcu(addr, &net_params->local_addr_list, list) { + list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { if (!addr->valid) continue; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html