Change in osmo-msc[master]: large refactoring: support inter-BSC and inter-MSC Handover

Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Tue May 7 23:39:56 UTC 2019


Neels Hofmeyr has posted comments on this change. ( https://gerrit.osmocom.org/13137 )

Change subject: large refactoring: support inter-BSC and inter-MSC Handover
......................................................................


Patch Set 9:

(28 comments)

hmm, my idea was to have received this review a lot earlier. I am N times through final-final and absolutely final testing after patch changes. I appreciate the review, but to be honest I personally need to get this load off my shoulders. I am applying your review thus far, but would prefer to not squash more modifications into this patch set, but rather move on to separate follow-up patches after this.

This patch being in limbo is a huge burden:

- having to continuously rebase it keeps introducing merge conflicts that are completely loaded onto my shoulders -- I have to understand and adjust to all other work going on; this limbo has been going on for far too long and by now is profoundly impacting my private life (stress / frustration).

- Secondly, squashing changes into the patch set happens sort of hidden, not seen in the git history; I've often had to revisit the reflog to analyse past versions of the patch set to fix bugs introduced by modifications squashed into this -- that's not how version control should happen.

So please, unless you have absolutely critical bugs that need fixing, let's move to merge + separate patches as soon as possible.

Nevertheless: many thanks for reviewing this with close scrutiny!
If you can, by all means please go on to do so!

https://gerrit.osmocom.org/#/c/13137/9/include/osmocom/msc/Makefile.am
File include/osmocom/msc/Makefile.am:

https://gerrit.osmocom.org/#/c/13137/9/include/osmocom/msc/Makefile.am@9
PS9, Line 9: gsm_04_11.h \
> Looks like a meaningless change.
I think I decided to alphabetically sort (vim ':sort' command) ... can we just keep this?


https://gerrit.osmocom.org/#/c/13137/6/include/osmocom/msc/msc_roles.h
File include/osmocom/msc/msc_roles.h:

https://gerrit.osmocom.org/#/c/13137/6/include/osmocom/msc/msc_roles.h@379
PS6, Line 379: struct an_apdu {
             : 	/* accessNetworkProtocolId */
             : 	enum osmo_gsup_access_network_protocol an_proto;
             : 	/* signalInfo */
             : 	struct msgb *msg;
             : 	/* If this AN-APDU is sent between MSCs, additional information from the E-interface messaging, like the
             : 	 * Handover Number, will placed/available here. Otherwise may be left NULL. */
             : 	const struct osmo_gsup_message *e_info;
             : };
> hmm, indeed, didn't see that... […]
In the end decided against using the msgb->cb[], because it makes the type conversions a lot more complex / ugly.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c
File src/libmsc/call_leg.c:

https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@34
PS9, Line 34: LOG_CALL_LEG
> LOGPFSML can handle fi=NULL, so we probably don't need this macro.
indeed it ended up being a simplistic wrapper, but it is my preferred pattern to keep FSM specific log macros. That way we can trivially tweak all log context for a given object in a single place.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@78
PS9, Line 78: fi
> AFAICS, you're using 'fi' as the talloc-parent in order to deallocate it automatically when the 'fi' […]
I want the struct and the fi to be one talloc unit, and I specifically do not want to have to remember to talloc_free in a cleanup function.

It is also a functional requirement to keep the struct around until the FSM instance frees to avoid all sorts of complex freeing cascades hitting use-after-free problems. See http://git.osmocom.org/libosmocore/commit/?id=1f9cc018618e7d1e9a7a37e1ef08e059a4e02e87 -- which would be quite useless if the cleanup function freed the struct separately.

You will see this exact pattern in *all* of the FSM instance implementations I have written, both in osmo-bsc and here. I appreciate your opinion, but will not adjust this pattern.

I don't understand what you mean by "no need to init dummy call_leg_fsm on line #59." -- line 59 has the global FSM definition, which is not the FSM instance that is allocated here based on that singleton FSM definition. Again this is a common pattern.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@78
PS9, Line 78: talloc_zero
> Since you're doing *cl = (struct call_leg) { ... […]
you mean I don't need to talloc_zero()? Below cl = (struct...){...} can be seen as syntactic sugar to not have to repeat cl-> in every line, and to make clear that the struct is fully initialized.
The talloc API does not provide a macro similar to talloc_zero() that names the struct but doesn't zero initialize.
What is the reason for this statement, optimization? I would just keep it as is, no point in changing it?


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@101
PS9, Line 101: cl->fi
> Looks like a bug to me. […]
osmo_fsm_inst_change_reparent() indeed contains this bug.
Thanks for highlighting, I found it while neck deep in developing and forgot about it.

Opened https://osmocom.org/issues/3983

Since we need an osmo_fsm_inst_change_parent2() for compat, this code can be merged as-is now, and can be fixed once the new osmo_fsm_inst_change_parent2() exists.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@142
PS9, Line 142: 
> ws
the blank line is intentional


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@145
PS9, Line 145: for (i = 0; i < ARRAY_SIZE(cl->rtp); i++) {
> So here we check whether all RTP connections of this call leg are established, right? Would be great […]
IMHO the code is quite clear, but ok.

What you see as simplification is code duplication in my eyes. I prefer to traverse arrays in for loops, even if they have only two members.

We don't suppress. Incoming event is an RTP stream saying it is ready, and if all are ready we pass on the *CALL_LEG* event that the entire call leg is established. No logging needed besides the events that are already logged.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@153
PS9, Line 153: if (cl->fi->state != CALL_LEG_ST_ESTABLISHED)
> This check could be done before iterating over 'cl->rtp': […]
I don't remember why I added this if()... theoretically, if any call leg is non-established, the call leg should also not be in established state.

I think I would rather remove the if() and have some error log when re-entering the same state...


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@158
PS9, Line 158: rtps = data;
> This assignment looks useless to me. You could pass 'data' directly to osmo_fsm_inst_dispatch().
it is to clarify the type of the data argument. Otherwise the reader has to move to other parts of the code to investigate what the type is intended to be. It is a common pattern that indeed doesn't have much functional use in this case, yet I would prefer to keep it.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@178
PS9, Line 178: struct call_leg *cl = fi->priv;
> Same here, just pass 'fi->priv' directly to osmo_fsm_inst_dispatch(). […]
same humble opinion, would prefer to keep for some degree of "type safety"


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@211
PS9, Line 211: {}
> I know that you prefer this way of array-termination, but in general we use { 0, NULL }. […]
I am being consistent with using {} everywhere in my patches all over the place for years :P
The cat is already out of the bag.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@229
PS9, Line 229: call_leg_fsm_establishing_established
> The function name looks confusing... […]
one function for both states


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@244
PS9, Line 244: /* same action function as above */
> Ok, now I see. […]
it is mostly for logging


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@248
PS9, Line 248: in_event_mask
> Since we terminate the FSM instance as soon as we enter this state, is there a chance that it would  […]
of course, cleanup and termination events ricocheting often dispatch numerous events


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@253
PS9, Line 253: /* same action function as above */
> Copy-pasted ;)
thx


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@257
PS9, Line 257: static struct osmo_fsm call_leg_fsm
> This symbol was already defined at line #59.
it obviously has to be done exactly this way, unless I move the alloc function to below here. I prefer it in the beginning though. It's called "forward declaration" and is a common tool in the C language.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/call_leg.c@290
PS9, Line 290: call_leg_ensure_rtp_alloc
> Basically, this function just calls call_leg_rtp_alloc() and checks if the allocation was successful […]
the critical difference is that it calls call_leg_rtp_alloc() only if it hasn't been called yet on that rtp_stream. I would like to keep this.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/e_link.c
File src/libmsc/e_link.c:

https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/e_link.c@77
PS9, Line 77: *e = (struct e_link) {
> I think you're abusing this way of structure initialization here. […]
I prefer this to clearly indicate that the struct is initialized from scratch. You are right that it seems unnecessary, but nevertheless is a common patter I use everywhere:

   foo = talloc
   *foo = (struct foo){
        initialze all members that can be initialized inline like this
   }

   initialize all members that need multiple lines and function calls, like memcpy and so forth

what's the point of changing this...


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/e_link.c@84
PS9, Line 84: memcpy
> If 'remote_name' were of type 'const char *', you could just use osmo_strdup(). […]
it is a blob with length, to one day support Global Title or something. Wasn't my idea, but it is a BLOB, not a char*.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/e_link.c@105
PS9, Line 105: enum msc_role from_role
> Unused parameter?
indeed, came from an earlier patch set where the role was reflected in the GSUP_ENTITY. Now we have just the GSUP_MESSAGE_CLASS


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/e_link.c@127
PS9, Line 127: strlen(local_msc_name)
> Do we need to also include '\0'?
yes :/ it's a long story...


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/e_link.c@132
PS9, Line 132: if (vsub)
> AFAIR, IMSI is mandatory for all GSUP messages. […]
the idea is that e_prep_gsup_msg() is generally working. If the result is an invalid message, tough luck for the caller, but I definitely want to avoid null pointer access. The caller might be aware of a missing vsub and obtain the IMSI otherwise? (not sure if any such caller exists, but that is the semantic idea of this function)


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/gsm_04_08.c
File src/libmsc/gsm_04_08.c:

https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/gsm_04_08.c@156
PS9, Line 156: DEBUGP
> How about LOG_MSC_A_CAT() here?
yes. This is legacy logging, not sure if we really need to change all of it now?
I agree that this can be changed but will not spend time on it.
Feel free to post a follow-up patch.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/gsm_04_08.c@279
PS9, Line 279: switch
> if (gsm48_hdr_msg_type(gh) != GSM48_MT_RR_PAG_RESP) […]
no: one day another message type comes along and we need to change to a switch() again.
Following same pattern as above.


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/gsm_04_08.c@409
PS9, Line 409: 		msc_a_put(msc_a, __func__);
> Shouldn't we also msc_a_put(MSC_A_USE_LOCATION_UPDATING) here?
the MSC_A_USE_LOCATION_UPDATING is put() by the FSM instance


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/gsm_04_08.c@719
PS9, Line 719: sizeof(struct gsm48_service_request*)
> Wait, sizeof pointer?!? Looks like a bug.
hmmm

this bug predates this patch, feel free to fix separately


https://gerrit.osmocom.org/#/c/13137/9/src/libmsc/gsm_04_08.c@1302
PS9, Line 1302: cm_service_type
> Unused?
defined by vlr.ops API, even if we don't use it, we comply with that cb signature



-- 
To view, visit https://gerrit.osmocom.org/13137
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-MessageType: comment
Gerrit-Change-Id: I27e4988e0371808b512c757d2b52ada1615067bd
Gerrit-Change-Number: 13137
Gerrit-PatchSet: 9
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>
Gerrit-CC: Harald Welte <laforge at gnumonks.org>
Gerrit-CC: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Comment-Date: Tue, 07 May 2019 23:39:56 +0000
Gerrit-HasComments: Yes
Gerrit-HasLabels: No
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190507/43e898bd/attachment.html>


More information about the gerrit-log mailing list